Docker和保护密码

我最近一直在尝试与Docker一起构build一些服务来玩玩,而一件让我烦恼的事情是把密码放在一个Dockerfile中。 我是一名开发人员,因此在源代码中存储密码就像是一个重大的冲击。 如果这甚至是一个问题? 有没有什么好的约定如何处理Dockerfiles中的密码?

这肯定是一个问题。 Dockerfiles通常检入到存储库并与其他人共享。 另一种方法是在运行时提供任何凭据(用户名,密码,令牌,任何敏感的东西) 作为环境variables 。 这可以通过-e参数(对于CLI上的单个variables)或--env-file参数(对于--env-file中的多个variables)来docker run

然而,环境variables也不是特别安全。 它们通过docker inspect可见,因此它们可供任何可以运行docker命令的用户使用。 (当然,任何有权访问主机上的docker用户也都有root权限 。)

我的首选模式是使用包装脚本作为ENTRYPOINTCMD 。 包装脚本可以首先将外部位置的秘密在运行时导入容器,然后执行应用程序,提供秘密。 其确切的机制取决于您的运行时环境。 在AWS中,可以使用IAMangular色, 密钥pipe理服务和S3的组合将encryption的秘密存储在S3存储桶中。 像HashiCorp Vault或credstash是另一种select。

AFAIK没有使用敏感数据作为构build过程的一部分的最佳模式。 事实上,我对这个话题有个疑问 。 您可以使用docker-squash从图像中移除图层。 但是为此,Docker中没有本地function。

你可能会发现shykes 对容器中的configuration有用的评论 。

我们的团队避免将证书放在存储库中,这意味着它们不被允许在Dockerfile 。 我们在应用程序中的最佳实践是使用来自环境variables的声明。

我们使用docker-compose来解决这个问题。

docker-compose.yml ,你可以指定一个包含容器环境variables的文件:

  env_file: - .env 

确保将.env添加到.gitignore ,然后在.env文件中设置凭据,如:

 SOME_USERNAME=myUser SOME_PWD_VAR=myPwd 

.env文件存储在本地或安全的地方,其余的团队可以抓住它。

请参阅: https : //docs.docker.com/compose/environment-variables/#/the-env-file

你不应该添加证书到一个容器,除非你可以向任何可以下载图像的人传播信任。 尤其是,执行和ADD creds和后来的RUN rm creds是不安全的,因为信用文件保留在中间文件系统层的最终映像中。 任何有权访问该映像的人都可以很容易地将其提取出来。

我看到的典型的解决scheme,当你需要信任结帐依赖关系,这是使用一个容器来build立另一个。 也就是说,通常在基本容器中有一些构build环境,并且需要调用它来构build应用程序容器。 所以简单的解决scheme是添加你的应用程序源,然后RUN生成命令。 这是不安全的,如果你需要在该RUN信用。 相反,你所做的是把你的源代码放到一个本地目录中,运行(如在docker run )容器来执行构build步骤,将本地源代码目录挂载为卷,并将注入或挂载为另一个卷。 构build步骤完成后,只需ADD现在包含构build工件的本地源目录即可构build最终容器。

我希望Docker增加了一些function来简化这一切!

更新:看起来像前进的方法将是嵌套的构build。 简而言之,dockerfile将描述用于构build运行时环境的第一个容器,然后描述第二个嵌套容器构build,可以将所有构件组装到最终容器中。 这样的构build时间的东西是不是在第二个容器。 这是一个Java应用程序,您需要JDK来构build应用程序,但只有JR​​E才能运行它。 有许多build议正在讨论中,最好从https://github.com/docker/docker/issues/7115开始,并按照其他build议的一些链接进行。;

现在Docker(版本1.13或17.06和更高版本)支持pipe理机密信息。 这是一个概述和更详细的文档

类似的function存在于kubernetes和DCOS中

使用Docker v1.9,您可以使用ARG指令将命令行传递的参数提取到构build操作中的图像上。 只需使用–build-arg标志。 所以你可以避免在Dockerfile上保留明确的密码(或其他合理的信息),并且可以直接传递它们。

来源: https : //docs.docker.com/engine/reference/commandline/build/ http://docs.docker.com/engine/reference/builder/#arg

例:

Dockerfile

 FROM busybox ARG user RUN echo "user is $user" 

build立图像命令

 docker build --build-arg user=capuccino -t test_arguments -f path/to/dockerfile . 

在构build期间打印

 $ docker build --build-arg user=capuccino -t test_arguments -f ./test_args.Dockerfile . Sending build context to Docker daemon 2.048 kB Step 1 : FROM busybox ---> c51f86c28340 Step 2 : ARG user ---> Running in 43a4aa0e421d ---> f0359070fc8f Removing intermediate container 43a4aa0e421d Step 3 : RUN echo "user is $user" ---> Running in 4360fb10d46a **user is capuccino** ---> 1408147c1cb9 Removing intermediate container 4360fb10d46a Successfully built 1408147c1cb9 

希望能帮助到你! 再见。

虽然我完全同意没有简单的解决scheme。 仍然有一个单一的失败点。 dockerfile,etcd等等。 Apcera有一个计划,看起来像伙伴 – 双authentication。 换句话说,除非有Apceraconfiguration规则,否则两个容器不能通话。 在他们的演示中,uid / pwd是清晰的,在pipe理员configuration链接之前不能重复使用。 然而,为了这个工作,这可能意味着修补Docker或至lessnetworking插件(如果有这样的事情)。

作为使用环境variables的一个替代方法,如果你有很多环境variables,可以使用它们,那就是使用卷在容器中访问主机上的一个目录。

如果你把所有的凭证作为文件放在那个文件夹中,那么容器就可以读取这些文件,并且可以随意使用它们。

例如:

 $ echo "secret" > /root/configs/password.txt $ docker run -v /root/configs:/cfg ... In the Docker container: # echo Password is `cat /cfg/password.txt` Password is secret 

许多程序可以从一个单独的文件读取他们的凭据,所以这样你可以将程序指向其中的一个文件。

我的方法似乎工作,但可能是天真的。 告诉我为什么这是错的。

docker build期间设置的ARGs被history子命令公开,所以不要去那里。 但是,运行容器时,运行命令中给出的环境variables对容器可用,但不是图像的一部分。

所以,在Dockerfile中,请设置不涉及秘密数据的设置。 设置一个类似/root/finish.sh的CMD。 在运行命令中,使用环境variables将秘密数据发送到容器中。 finish.sh基本上使用variables来完成构build任务。

为了更方便地pipe理秘密数据,把它放到一个由--env-file运行加载--env-file开关--env-file 。 当然,保持文件的秘密。 .gitignore等。

对我来说, finish.sh运行一个Python程序。 它检查以确保它以前没有运行,然后完成设置(例如,将数据库名称复制到Django的settings.py )。