我最近一直在尝试使用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
...
其他回答
我们的团队避免将凭证放在存储库中,因此这意味着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
我的方法似乎有效,但可能有些幼稚。告诉我为什么这是错的。
在docker构建过程中设置的arg是由history子命令公开的,所以不要去那里。但是,在运行容器时,run命令中给出的环境变量对容器是可用的,但不是映像的一部分。
因此,在Dockerfile中,执行不涉及秘密数据的设置。设置一个类似于/root/finish.sh的CMD。在run命令中,使用环境变量将秘密数据发送到容器中。sh使用这些变量来完成构建任务。
为了更容易地管理秘密数据,将其放入一个文件中,由docker使用——env-file开关加载。当然,要保密。gitignore之类的。
对我来说,finish.sh运行一个Python程序。它检查以确保之前没有运行过,然后完成设置(例如,将数据库名称复制到Django的settings.py中)。
永远不要向容器添加凭据,除非您可以将凭据广播给任何可以下载映像的人。特别是,执行并添加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.
Docker现在(版本1.13或17.06或更高)支持管理秘密信息。下面是概述和更详细的文档
kubernetes和DCOS也存在类似的特征
仅运行时解决方案
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秘密
推荐文章
- Docker和安全密码
- 如何让Docker容器在系统引导时自动启动?
- 如何在Docker容器中用模式初始化MySQL数据库?
- 准备好的语句如何防止SQL注入攻击?
- PYTHONUNBUFFERED在docker文件中的用途是什么?
- Xcode:构建失败,但没有错误消息
- 如何在Dockerfile CMD中使用变量?
- 将主机端口转发到docker容器
- “docker compose”与“docker-compose”的区别
- /bin/sh: apt-get:未找到
- 为什么人们会写“throw 1;<不要邪恶>”和“for(;;);”在json响应前?
- 非加密用途的最快哈希?
- 如何在docker映像的新容器中运行bash ?
- docker -撰写持久数据MySQL
- SHA512 vs. Blowfish和Bcrypt