最近我一直在使用Docker进行各种服务的构建和尝试,但有个问题一直困扰着我——如何在Dockerfile中存储密码?作为开发者,将密码存储在源代码中让人感到非常不安。这是否应该成为一个问题?有没有好的惯例来处理Dockerfile中的密码?
-e
参数(用于CLI上的单个变量)或--env-file
参数(用于文件中的多个变量)传递给docker run
来实现。阅读此处以了解如何在docker-compose中使用环境变量。--env-file
绝对是更安全的选择,因为它可以防止在使用set -x
时将机密信息显示在ps
或日志中。docker inspect
查看,并且因此可供任何能够运行 docker
命令的用户使用。(当然,任何在主机上具有 docker
访问权限的用户都已经 拥有 root 权限 了。)ENTRYPOINT
或 CMD
。包装脚本可以在运行时首先从外部位置导入秘密到容器中,然后执行应用程序,提供秘密。这个过程的确切机制根据您的运行时环境而异。在 AWS 中,您可以使用 IAM 角色、密钥管理服务和 S3 在 S3 存储桶中存储加密的秘密。类似 HashiCorp Vault 或 credstash 的工具也是一个选择。docker inspect
中。 - slim我们的团队避免将凭据放入存储库中,因此这意味着它们不允许出现在Dockerfile
中。在应用程序内部,我们的最佳实践是使用来自环境变量的凭据。
我们通过使用docker-compose
来解决这个问题。
在docker-compose.yml
中,您可以指定一个文件,其中包含容器的环境变量:
env_file:
- .env
请务必在.gitignore
中添加.env
,然后在.env
文件中设置凭据,例如:
SOME_USERNAME=myUser
SOME_PWD_VAR=myPwd
将.env
文件存储在本地或其他团队成员可以获取的安全位置。
参见:https://docs.docker.com/compose/environment-variables/#/the-env-file
.gitignore
so that the .env
file with sensitive information does not get checked-in to GitHub. I'm pretty sure this won't work if you add it .dockerignore
- theUtherSideDocker现在支持管理私密信息,版本号为1.13或17.06及更高版本。这里是一个概述和更详细的文档
Kubernetes和DCOS也有类似的功能。
docker secret create
:创建一个秘密 docker secret inspect
:显示有关秘密的详细信息 docker secret ls
:查看所有秘密 docker secret rm
:删除特定的秘密 --secret
标志用于 docker service create
:在服务创建期间创建一个秘密 --secret-add
和 --secret-rm
标志用于 docker service update
:在服务更新任务期间更新秘密的值或删除秘密。Docker secrets 在管理节点上处于静止状态,并在容器启动期间向工作节点供应。 - P.JADD凭据
,然后再RUN rm凭据
并不安全,因为凭据文件仍然存在于最终镜像中的一个中间文件系统层中。任何有权访问该镜像的人都可以轻松提取它。RUN
构建命令。如果您需要在该RUN
中使用凭据,则此方法不安全。相反,您需要将源代码放入本地目录,运行(如docker run
)容器以使用挂载为卷的本地源目录执行构建步骤,并将凭据注入或作为另一个卷挂载。完成构建步骤后,通过仅ADD
本地源目录(其中现在包含构建的工件)来构建最终容器。仅运行时解决方案
docker-compose还提供了一个非Swarm模式的解决方案(自v1.11以来: 使用绑定挂载的Secrets)。
Secrets作为文件被挂载到/run/secrets/
下,由docker-compose处理。这解决了在运行容器时的问题,但不解决构建镜像时的问题,因为/run/secrets/
在构建镜像时未被挂载。此外,此行为取决于使用docker-compose运行容器。
示例:
Dockerfile
FROM alpine
CMD cat /run/secrets/password
docker-compose.yml
version: '3.1'
services:
app:
build: .
secrets:
- password
secrets:
password:
file: password.txt
要构建,请执行:
docker-compose up -d
更多阅读资料:
DOCKER_BUILDKIT=1 docker-compose up -d
。 - Robin Dinse如果你有很多环境变量,使用它们可能会变得混乱不堪。此时可以使用主机文件夹,在容器中使其可访问,作为一种替代方案。
如果你将所有凭据存储在该文件夹中,则容器可以读取文件并随意使用。
例如:
$ 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子命令公开,因此无法使用。然而,在运行容器时,run命令中提供的环境变量可用于容器,但不是镜像的一部分。
因此,在Dockerfile中,进行不涉及机密数据的设置。将CMD设置为类似于/root/finish.sh
的内容。在运行命令中,使用环境变量将秘密数据发送到容器中。 finish.sh
基本上使用这些变量来完成构建任务。
为了更轻松地管理机密数据,请将其放入一个文件中,并使用--env-file
开关加载该文件。当然,要保持文件的机密性,如.gitignore等。
对于我来说,finish.sh
运行一个Python程序。它检查是否已经运行过,然后完成设置(例如,将数据库名称复制到Django的settings.py
中)。
现在有一个新的docker命令用于“secrets”管理。但这只适用于群集。
docker service create
--name my-iis
--publish target=8000,port=8000
--secret src=homepage,target="\inetpub\wwwroot\index.html"
microsoft/iis:nanoserver
2020年9月,Sebastiaan van Stijn 更新了 问题13490“秘密:撰写最佳实践、要点与不要点、路线图”。
使用
buildkit
作为构建器时,现在可以使用构建时间机密;请参阅来自 Tõnis Tiigi 的博客文章 "Docker 18.09 中的构建机密和 SSH 转发",发布于2018年11月。
文档已更新:"使用 BuildKit 构建镜像"
那最后一部分是新的(2020年9月)。
RUN --mount
选项用于机密将很快成为默认(稳定)的Dockerfile
语法。
New Docker Build secret information
The new
--secret
flag for docker build allows the user to pass secret information to be used in the Dockerfile for building docker images in a safe way that will not end up stored in the final image.
id
is the identifier to pass into thedocker build --secret
.
This identifier is associated with theRUN --mount
identifier to use in the Dockerfile.
Docker does not use the filename of where the secret is kept outside of the Dockerfile, since this may be sensitive information.
dst
renames the secret file to a specific file in the DockerfileRUN
command to use.For example, with a secret piece of information stored in a text file:
$ echo 'WARMACHINEROX' > mysecret.txt
And with a Dockerfile that specifies use of a BuildKit frontend docker/dockerfile:1.0-experimental, the secret can be accessed.
For example:
# syntax = docker/dockerfile:1.0-experimental
FROM alpine
# shows secret from default secret location:
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
# shows secret from custom secret location:
RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar
$ docker build --no-cache --progress=plain --secret id=mysecret,src=mysecret.txt .
...
#8 [2/3] RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
#8 digest: sha256:5d8cbaeb66183993700828632bfbde246cae8feded11aad40e524f54ce7438d6
#8 name: "[2/3] RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret"
#8 started: 2018-08-31 21:03:30.703550864 +0000 UTC
#8 1.081 WARMACHINEROX
#8 completed: 2018-08-31 21:03:32.051053831 +0000 UTC
#8 duration: 1.347502967s
#9 [3/3] RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar
#9 digest: sha256:6c7ebda4599ec6acb40358017e51ccb4c5471dc434573b9b7188143757459efa
#9 name: "[3/3] RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar"
#9 started: 2018-08-31 21:03:32.052880985 +0000 UTC
#9 1.216 WARMACHINEROX
#9 completed: 2018-08-31 21:03:33.523282118 +0000 UTC
#9 duration: 1.470401133s
...
12-Factor应用程序方法指出,任何配置都应存储在环境变量中。
Docker compose可以在配置中进行变量替换,因此可以用于将密码从主机传递到docker中。