我最近一直在尝试使用Docker构建一些服务,有一件事一直困扰着我,那就是把密码放在Dockerfile中。我是一名开发人员,所以在源代码中存储密码感觉就像在脸上打了一拳。这值得担心吗?Dockerfiles中有什么好的处理密码的约定吗?
当前回答
第13490期“秘密:记录最佳实践,做什么和不做什么,路线图”在2020年9月刚刚得到了新的更新,来自塞巴斯蒂安·范·斯泰因:
当使用buildkit作为构建器时,构建时间秘密现在是可能的;请参阅2018年11月Tõnis Tiigi的博客文章“在Docker 18.09中构建秘密和SSH转发”。
文档更新:“用BuildKit构建图像”
用于秘密的RUN——mount选项将很快升级为默认的(稳定的)Dockerfile语法。
最后一部分是新的(2020年9月)
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 the docker build --secret. This identifier is associated with the RUN --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 Dockerfile RUN 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
这个Dockerfile只是为了证明这个秘密可以被访问。正如您可以在构建输出中看到的那样。最终构建的图像将没有秘密文件:
$ 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
...
其他回答
第13490期“秘密:记录最佳实践,做什么和不做什么,路线图”在2020年9月刚刚得到了新的更新,来自塞巴斯蒂安·范·斯泰因:
当使用buildkit作为构建器时,构建时间秘密现在是可能的;请参阅2018年11月Tõnis Tiigi的博客文章“在Docker 18.09中构建秘密和SSH转发”。
文档更新:“用BuildKit构建图像”
用于秘密的RUN——mount选项将很快升级为默认的(稳定的)Dockerfile语法。
最后一部分是新的(2020年9月)
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 the docker build --secret. This identifier is associated with the RUN --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 Dockerfile RUN 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
这个Dockerfile只是为了证明这个秘密可以被访问。正如您可以在构建输出中看到的那样。最终构建的图像将没有秘密文件:
$ 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
...
这肯定是一个问题。dockerfile通常被签入存储库并与其他人共享。另一种方法是在运行时提供任何凭据(用户名、密码、令牌,任何敏感的东西)作为环境变量。这可以通过-e参数(用于CLI中的单个变量)或——env-file参数(用于文件中的多个变量)来运行docker。阅读这篇文章,了解如何在docker-compose中使用环境。
使用——env-file绝对是一个更安全的选择,因为如果使用set -x,它可以防止秘密显示在ps或日志中。
然而,环境变量也不是特别安全。通过docker inspect可以看到它们,因此任何可以运行docker命令的用户都可以使用它们。(当然,在主机上可以访问docker的任何用户都有root权限。)
我更喜欢的模式是使用包装器脚本作为ENTRYPOINT或CMD。包装器脚本可以首先在运行时将秘密从外部位置导入到容器中,然后执行应用程序,提供秘密。具体的机制取决于您的运行时环境。在AWS中,您可以使用IAM角色、密钥管理服务和S3的组合来将加密的秘密存储在S3桶中。HashiCorp Vault或credstash是另一种选择。
在构建过程中使用敏感数据没有最佳模式。事实上,我有一个关于这个话题的SO问题。您可以使用docker-squash从映像中删除图层。但是Docker中并没有用于此目的的本机功能。
您可能会发现在容器中对配置的shykes注释很有用。
从版本20.10开始,除了使用secret-file,您还可以直接使用env提供秘密。
Buildkit: secrets:允许提供秘密与env moby/moby#41234 docker/cli#2656 moby/ Buildkit #1534 支持——secret id=foo,env=MY_ENV作为将秘密值存储到文件的替代方案。 ——secret id=GIT_AUTH_TOKEN将加载env,如果它存在,而文件不存在。
秘密文件:
THIS IS SECRET
Dockerfile:
# syntax = docker/dockerfile:1.3
FROM python:3.8-slim-buster
COPY build-script.sh .
RUN --mount=type=secret,id=mysecret ./build-script.sh
build-script.sh:
cat /run/secrets/mysecret
执行:
$ export MYSECRET=theverysecretpassword
$ export DOCKER_BUILDKIT=1
$ docker build --progress=plain --secret id=mysecret,env=MYSECRET -t abc:1 . --no-cache
......
#9 [stage-0 3/3] RUN --mount=type=secret,id=mysecret ./build-script.sh
#9 sha256:e32137e3eeb0fe2e4b515862f4cd6df4b73019567ae0f49eb5896a10e3f7c94e
#9 0.931 theverysecretpassword#9 DONE 1.5s
......
在Docker v1.9中,你可以使用ARG指令在构建操作时获取通过命令行传递给映像的参数。只需使用——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"
生成映像命令
docker build --build-arg user=capuccino -t test_arguments -f path/to/dockerfile .
在构建过程中打印
$ 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
希望能有所帮助!再见。
我们的团队避免将凭证放在存储库中,因此这意味着Dockerfile中不允许使用凭证。我们在应用程序中的最佳实践是使用来自环境变量的信用。
我们使用docker-compose来解决这个问题。
docker-compose之内。Yml,你可以为容器指定一个包含环境变量的文件:
env_file:
- .env
确保将.env添加到.gitignore,然后在.env文件中设置凭据,如下所示:
SOME_USERNAME=myUser
SOME_PWD_VAR=myPwd
将.env文件存储在本地或其他团队成员可以获取它的安全位置。
见:https://docs.docker.com/compose/environment-variables/ / the-env-file
推荐文章
- Gradle构建脚本依赖项
- 守护进程的错误响应:已被集装箱使用"
- Xcode的构建文件夹在哪里?
- 如何从DockerFile运行docker实例?
- 我是否试图连接到启用TLS的没有TLS的守护进程?
- Docker -一种访问主机USB或串行设备的方法?
- Docker:无效引用格式
- 将AWS凭证传递给Docker容器的最佳方法是什么?
- 如何在docker-compose中设置主机名?
- 为什么Docker容器映像这么大?
- 在php中生成一个随机密码
- java.util.Random和java.security. securerrandom的区别
- 如何在docker撰写版本3中指定内存和CPU限制
- Docker和安全密码
- 如何让Docker容器在系统引导时自动启动?