密钥绝不可硬编码或通过构建参数注入dockerfile,否则会残留于镜像层并被轻易提取;应运行时挂载文件、环境变量注入或集成secret管理服务,构建阶段仅限buildkit --secret临时使用。
不能在 dockerfile 中直接写密码或密钥,也不能用 arg + env 组合传入后保存到镜像里——这些做法会让密钥固化在镜像层中,通过 docker history 或解包就能轻易提取。
必须禁用的危险方式
以下操作看似方便,实则严重泄露风险:
-
COPY 或 ADD 含密钥的本地文件(如
COPY config.json /app/) -
用 ARG 接收再赋值给 ENV(如
ARG DB_PASS→ENV DATABASE_PASSWORD=$DB_PASS) -
RUN 命令中 echo/curl 写入密钥并删除(即使加
rm -f,该层仍完整保留原始内容)
构建阶段唯一安全的临时方案:BuildKit --secret
仅当构建过程确实需要密钥(例如拉取私有 Git 仓库、访问私有包源),才启用 BuildKit 并使用 --secret。它不写入镜像,进程退出即销毁。
- 启用 BuildKit:
DOCKER_BUILDKIT=1 docker build ... - 挂载 SSH 密钥:
docker build --secret id=ssh_key,src=$HOME/.ssh/id_rsa . - Dockerfile 中使用:
RUN --mount=type=secret,id=ssh_key ssh-add /run/secrets/ssh_key && git clone ... - 对 pip/npm 私有源,优先用
.netrc或auth.conf配置,并通过--secret注入
更推荐:完全避开构建时依赖
绝大多数场景下,密钥根本不需要出现在构建阶段。应把敏感信息延迟到容器启动时注入:
-
运行时挂载只读文件:启动时用
docker run -v /host/secrets:/run/secrets:ro,确保宿主机文件权限为600 -
环境变量注入(非构建时):用
docker run --env-file .env或 Docker Compose 的env_file字段 - 对接 Secret 管理服务:Kubernetes Secret、Docker Swarm secret、AWS Secrets Manager、HashiCorp Vault 等,应用启动时按需获取
配套加固措施
技术方案之外,流程管控同样关键:
- CI/CD 中禁用长期密钥,改用短期令牌(如 GitHub OIDC、AWS STS)
- 在流水线中加入静态扫描,检测提交内容是否含
password:、-----BEGIN RSA PRIVATE KEY-----等特征 - 定期用 Trivy 或 Snyk 扫描中间镜像和最终镜像,识别意外残留的密钥字符串
- 构建完成后立即清理 CI 节点上的临时凭据文件











