传递用于构建 Docker 镜像的安全信息

2021-08-08 19:52:32

非常感谢从 Docker 映像中访问 Nexus 或 GitHub 存储库等私有资源,并且不泄露任何与安全相关的信息。首先,我们绝不会直接在 Dockerfile 中包含凭据或任何其他安全信息。其次,可以创建多阶段¹构建并从任何私人信息中清除最终图像和图层。然而,这不是一个简单的解决方案,在很大程度上取决于谁在开发。最后,我们中的一些人可以依靠使用参数——ARG——并在 docker build² 命令中传递信息。然而,仅此而已,图像层中的秘密信息可用。接下来我将展示一个例子。从 ubuntu ARG USERNAME ARG PASSWORD RUN apt-get update && \ apt-get upgrade && \ apt-get install -y curl RUN curl -o nginx_policy.yaml -u $USERNAME:$PASSWORD http://nexus:8081/repository/ raw/policy/nginx-policy.yaml docker build -t secret:args --build-arg USERNAME=$user --build-arg PASSWORD=$pass 。将构建上下文发送到 Docker 守护进程 3.072kB 步骤 1/5:从 ubuntu ---> c29284518f49 步骤 2/5:ARG 用户名 ---> 使用缓存 ---> 720c9732f5db 步骤 3/5:ARG 密码 ---> 使用缓存 ---> 193f8044461b 第 4/5 步:运行 apt-get update && apt-get upgrade && apt-get install -y curl ---> 使用缓存 ---> 894b791e5ec3 第 5/5 步:运行 curl -o nginx_policy .yaml -u $USERNAME:$PASSWORD http://172.17.0.2:8081/repository/raw/policy/nginx-policy.yaml ---> Using cache ---> e4050d5c1743 成功构建 e4050d5c1743 成功标记 secret:args I在 build-arg 选项中使用环境变量来不存储凭据操作系统历史记录。此外,在图像中,我没有将这些信息保存在任何地方。

当您针对此图像运行 docker history 命令时,会出现这种方法的问题: ➜ docker history secret:args_env IMAGE CREATED CREATED BY SIZE COMMENT f11cb0b139f3 2 分钟前 |2 PASSWORD=admin123 USERNAME=admin /bin/sh ... 0B 6ca5f3fc074a |2 PASSWORD=admin123 USERNAME=admin /bin/sh … 0B 193f8044461b 43 分钟前 /bin/sh -c #(nop) ARG 密码 0B 720c9732f5db 43 分钟前 /bin/sh -c #(nop) ARG USERNAME284f51b几天前 /bin/sh -c #(nop) CMD ["bash"] 0B <missing> 3 天前 /bin/sh -c #(nop) ADD file:5c3d9d2597e01d1ce... 72.8MB 显然,我们可以看到凭据存储在图像的元数据中。尽管我们尽了最大的努力,我们仍然在泄露机密信息。 Buildkit³ 与 Docker 精确集成⁴,以帮助我们保持安全。自 18.06 版本以来,Buildkit 出现在 Docker 中,目前仅支持 Linux 容器。要启用 Buildkit 构建,请在调用 docker build 命令时设置 DOCKER_BUILDKIT=1 环境变量,例如: docker build 的新 --secret 标志允许用户传递要在 Dockerfile 中使用的机密信息,以在一个不会最终存储在最终图像中的安全方式。要使用此功能,我们需要覆盖 Dockerfile 中的默认前端⁶。在 Dockerfile 的第一行输入: RUN 命令中添加了 --mount 标志,以允许构建容器访问安全文件,例如私钥,而无需将它们烘焙到映像中。

并且使用指定使用 BuildKit 前端 docker/dockerfile:1.2 的 Dockerfile,在执行 RUN 时可以访问机密:此 Dockerfile 仅用于证明可以访问机密。如您所见,构建输出中打印的秘密。最终构建的镜像将没有秘密文件: $ DOCKER_BUILDKIT=1 docker build --no-cache --progress=plain -t secret:buildkit --secret id=mysecret,src=mysecret.txt 。 5c65425f6fc0d6c65a5ddd6784812097b4eff778b9bcbf39bc708aacbad59abd#1转移dockerfile:从Dockerfile#1 SHA256#1 [内部]负载生成定义196B完成#1 DONE 0.0S#2内部]负载.dockerignore#2 SHA256:35c8e51716823a06d8dbd04a2594a31a90f3d02bb55a0b8c3e9f2c1b44f901c7#2传送上下文:2B完成#2 DONE对于docker.io/docker/dockerfile:1.2#3 SHA256 0.0S#3解析图像配置:b239a20f31d7f1e5744984df3d652780f1a82c37554dd73e1ad47c8eb05b0d69#3 DONE 2.5S#4搬运工图像://docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc#4 SHA256:37e0c519b0431ef5446f4dd0a4588ba695f961e9b0e800cd8c7f5ba6165af727#4决心docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc完成#4#CACHED 5内部]负载元数据docker.io/library/alpine:latest#5 SHA256:d4fb25f5b5c00defc20ce26f2efc4e288de8834ed5aa59dff877b495ba88fda6#5 DONE 0.0S #6 [1/2] 来自 docker.io/library/alpine #6 SHA256:665ba8b2cdc0cb0200e2a42a6b3c0f8f684089f4cd1b81494fbb9805879120f7#6#CACHED 7 [2/2] RUN --mount =类型=秘密,ID = mysecret猫/运行/秘密/ mysecret#7 SHA256:75601a522ebe80ada66dedd9dd86772ca932d30d7e1b11bba94c04aa55c237de#7 0.494 SUPER_SECRET_PASSWORD#7 DONE 0.5秒#8导出到图像#8 SHA256:e8c613e07b0b7ff33893b694f7759a10d42e180f2b4dc349fb57dc6b71dcab00#8层导出0.0S做过#8刻写的图像SHA256:8df0fe20ceab547858702c32456d962b99d66fd40ab29f4e191ac0b52e383039做过#8 DONE 0.0S $搬运工历史秘密:buildkit的形象创造的创SIZE条评论7da5afe4875316秒前RUN / bin / sh的-c猫/run/secrets/mysecret # b... 0B buildkit.dockerfile.v0 <missing> 4 周前 /bin/sh -c #(nop) CMD ["/bin/sh"] 0B <missing> 4 周前 /bin/ sh -c #(nop) ADD file:f278386b0cef68136... 5.6MB 可以使用环境变量⁷来传递秘密信息,而不是使用秘密文件,例如:本文解释了使用受限信息所需的步骤在 Docker 容器中更安全。通过在“docker build”之前设置一个环境变量并在 Dockerfile 中进行一些更改,您可以防止用于配置 Docker 容器的凭据泄露。

Docker Buildkit 不仅支持秘密,还支持其他构建挂载⁸,例如缓存和 ssh。开始或继续探索 Buildkit 并了解它如何帮助您提高环境的安全性。