菜单

Docker 中的秘钥管理

相关源文件

本文档概述了在为 Node.js 应用程序构建 Docker 镜像时处理敏感数据的安全方法。它专门关注防止 API 密钥、令牌和凭证等密钥在 Docker 镜像及其历史记录中泄露的技术。有关 Docker 构建优化的相关信息,请参阅多阶段构建和镜像优化

Docker 中 Secret 管理的挑战概述

由于 Docker 的分层架构,在 Docker 中安全地管理密钥带来了独特的挑战。Docker 镜像不仅仅是文件的集合,更是保存构建时发生事件历史的分层集合。在构建过程中暴露的任何密钥都可能被提取自

  1. 本地 Docker 历史记录
  2. Docker 仓库
  3. CI/CD 系统
  4. Docker 镜像本身

来源:sections/docker/avoid-build-time-secrets.md

常见的 Secret 泄露点

一种特别不安全的做法是将 Secret 作为构建参数传递。虽然这可能很方便,但这些 Secret 可以从 Docker 历史记录和其他记录了构建命令的地方提取出来。

需要保护的关键 Secret 文件

文件模式包含风险
.npmrcnpm 仓库令牌未经授权的软件包发布
.env环境变量API 密钥和服务凭证
.awsAWS 凭证云基础设施访问
credentials.*各种服务凭证服务冒充
id_rsa, *.pemSSH 密钥服务器访问

来源:sections/docker/docker-ignore.md13-28 sections/docker/avoid-build-time-secrets.md5-9

处理 Docker 中的 Secret 主要有三种方法,安全性各不相同

来源:sections/docker/avoid-build-time-secrets.md7-9

1. 使用 Docker 的 --secret 功能(推荐)

最安全的方法是使用 Docker 的 --secret 功能(在 Docker 18.09 中引入),它允许在构建时仅挂载 Secret。这些 Secret 不会保存在最终镜像、任何中间镜像或镜像提交历史中。

此方法需要在 Dockerfile 中使用实验性语法

来源:sections/docker/avoid-build-time-secrets.md12-29

2. 使用多阶段构建

多阶段构建在安全性和兼容性之间提供了良好的平衡。虽然 Secret 可能出现在本地 Docker 守护程序的构建缓存中,但它们不会出现在最终镜像或仓库中。

来源:sections/docker/avoid-build-time-secrets.md32-60 sections/docker/multi_stage_builds.md3-6

3. 使用 .dockerignore 防止 Secret 泄露

正确配置的 .dockerignore 文件提供了一个额外的安全层,通过防止敏感文件进入构建上下文。

来源:sections/docker/docker-ignore.md5-7

实施指南

设置 .dockerignore

在项目根目录创建一个 .dockerignore 文件,其中包含排除敏感文件的模式

# Node.js files
**/node_modules/
**/npm-debug.log

# Secret and config files
**/.env
**/.npmrc
**/.aws
**/credentials.*
**/*.pem
**/*.key

# Version control and IDE files
**/.git
**/.vscode
**/.idea

# Documentation and test files
**/README.md
**/test
**/coverage

来源:sections/docker/docker-ignore.md13-28

此方法要求 Docker 18.09 或更新版本并启用 BuildKit。

在您的 Dockerfile 中

构建时

来源:sections/docker/avoid-build-time-secrets.md12-29

方法二:使用多阶段构建

在您的 Dockerfile 中

构建时

重要提示:构建完成后,应从 Docker 守护程序中删除未标记的镜像,以消除 Secret 的痕迹。

来源:sections/docker/avoid-build-time-secrets.md32-60 sections/docker/multi_stage_builds.md78-121

应避免的反模式

1. 在单阶段构建中将 Secret 作为构建参数传递

这不安全,因为

  • 即使 Secret 在同一层中被删除,它仍然存在于 Docker 历史记录中
  • 它可以从 Docker 仓库和 CI 系统中检索
  • 任何拥有镜像访问权限的人都可能提取 Secret

来源:sections/docker/avoid-build-time-secrets.md65-86

2. 未使用 .dockerignore 递归复制所有文件

这不安全,因为它会将敏感文件复制到您的 Docker 镜像中。

来源:sections/docker/docker-ignore.md34-48

安全考量

即使采用了上述最佳实践,也请注意这些安全注意事项

  1. 本地 Docker 历史记录:使用多阶段构建时,Secret 仍存在于 Docker 守护程序的构建缓存中。对于高度敏感的环境,请考虑

    • 定期清理 Docker 构建缓存
    • 在隔离的、临时的环境中构建
  2. 构建系统日志:确保您的 CI/CD 系统正确处理 Secret,并且不记录它们。

  3. 仓库安全:确保您的 Docker 仓库具有适当的访问控制。

  4. Secret 轮换:即使您认为 Secret 是安全的,也要定期轮换它们。

  5. 审计:定期审计您的 Docker 镜像是否存在 Secret 泄露。

来源:sections/docker/avoid-build-time-secrets.md7-9 sections/docker/scan-images.md5-7

结论

Docker 中的正确 Secret 管理需要一种多层方法。最安全的选择是使用 Docker 的 --secret 功能,但多阶段构建提供了安全性和兼容性的良好平衡。始终使用 .dockerignore 来提供额外的安全层,从一开始就防止敏感文件进入构建上下文。

请记住,Docker 镜像会保留其构建历史,因此即使 Secret 没有出现在最终镜像中,在构建过程中暴露的 Secret 仍可能被提取。始终遵循最小权限原则,并最大程度地减少在整个容器生命周期中 Secret 的暴露。