我最近一直在尝试使用Docker构建一些服务,有一件事一直困扰着我,那就是把密码放在Dockerfile中。我是一名开发人员,所以在源代码中存储密码感觉就像在脸上打了一拳。这值得担心吗?Dockerfiles中有什么好的处理密码的约定吗?
当前回答
仅运行时解决方案
Docker-compose还提供了一个非群模式的解决方案(自v1.11起: 秘密使用绑定安装)。
这些秘密被docker-compose挂载为/run/secrets/下面的文件。这可以在运行时(运行容器)解决问题,但不能在构建时(构建映像)解决问题,因为/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
进一步阅读:
mikesir87的博客-在开发过程中使用Docker秘密
其他回答
使用环境变量的另一种替代方法是使用卷使容器中可以访问主机上的目录,如果环境变量太多,环境变量会变得很混乱。
如果您将所有凭据作为文件放在该文件夹中,那么容器就可以读取这些文件并根据需要使用它们。
例如:
$ 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
许多程序都可以从一个单独的文件中读取它们的凭据,因此通过这种方式,您可以将程序指向其中一个文件。
永远不要向容器添加凭据,除非您可以将凭据广播给任何可以下载映像的人。特别是,执行并添加creds并随后运行rm creds是不安全的,因为creds文件仍然保存在中间文件系统层的最终映像中。任何能接触到图像的人都能很容易地提取出来。
The typical solution I've seen when you need creds to checkout dependencies and such is to use one container to build another. I.e., typically you have some build environment in your base container and you need to invoke that to build your app container. So the simple solution is to add your app source and then RUN the build commands. This is insecure if you need creds in that RUN. Instead what you do is put your source into a local directory, run (as in docker run) the container to perform the build step with the local source directory mounted as volume and the creds either injected or mounted as another volume. Once the build step is complete you build your final container by simply ADDing the local source directory which now contains the built artifacts.
我希望Docker添加一些功能来简化这一切!
Update: looks like the method going forward will be to have nested builds. In short, the dockerfile would describe a first container that is used to build the run-time environment and then a second nested container build that can assemble all the pieces into the final container. This way the build-time stuff isn't in the second container. This of a Java app where you need the JDK for building the app but only the JRE for running it. There are a number of proposals being discussed, best to start from https://github.com/docker/docker/issues/7115 and follow some of the links for alternate proposals.
第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
...
在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
希望能有所帮助!再见。
Docker现在(版本1.13或17.06或更高)支持管理秘密信息。下面是概述和更详细的文档
kubernetes和DCOS也存在类似的特征
推荐文章
- 从Docker容器获取环境变量
- 阻止人们入侵基于php的Flash游戏高分表的最佳方法是什么
- E: gnupg, gnupg2和gnupg1似乎没有安装,但是这个操作需要其中一个
- VS2013外部构建错误"error MSB4019: The imported project <path> was not found"
- 如何从docker更改默认docker注册表。IO到我的私人注册表?
- Docker- compose无法连接到Docker Daemon
- 单个命令停止和删除docker容器
- 使用GPU从docker容器?
- 如何使用本地映像作为dockerfile的基本映像?
- 在子目录中测试Golang
- 谁能解释一下docker.sock
- 多重from是什么意思
- 通过映像名称停止Docker容器- Ubuntu
- 如果dockerfile的名称不是dockerfile,我如何构建一个dockerfile ?
- Gradle构建脚本依赖项