环境变量泄露是Docker镜像构建中最隐蔽也最危险的安全隐患之一,常将数据库密码、API密钥等敏感信息固化进镜像层,可通过docker history或inspect提取;必须禁用ENV/RUN export硬编码,改用构建参数传非敏感值、.dockerignore排除.env等文件、多阶段构建清理中间产物,并坚持运行时注入而非构建时注入。

环境变量泄露是Docker镜像构建中最隐蔽也最危险的安全隐患之一——它常在不经意间把数据库密码、API密钥、内部地址等敏感信息固化进镜像层,导致即使容器未运行,攻击者也能通过docker history或docker image inspect轻松提取。
避免在Dockerfile中直接写入敏感值
这是最基础也最关键的防线。禁止使用ENV或RUN export硬编码任何凭据或配置:
- ❌ 错误示例:
ENV DB_PASSWORD=prod123! ENV API_KEY=sk_live_abc - ✅ 正确做法:用构建参数(
--build-arg)传入非敏感值,且不保留到最终镜像;敏感值一律交由运行时注入 - 构建参数仅在构建阶段生效,需配合
ARG声明,并避免在RUN中拼接进文件(否则可能残留)
用.dockerignore排除敏感文件
很多泄露源于开发人员把.env、config.local.yml、secrets.json等文件随COPY . .一并打入镜像。必须在项目根目录配置.dockerignore:
- 明确列出所有不应进入镜像的文件和目录,例如:
.env、config/*.local、**/secrets/**、.git、node_modules、__pycache__ - 注意通配符行为:以
/开头表示从上下文根开始匹配;无/则为模糊匹配 - 可临时用
docker build --no-cache -f - . 测试是否还有意外文件被复制
多阶段构建中清理中间产物
即使用了ARG,若在构建阶段生成了含敏感信息的配置文件(如application.conf),又未清理,仍会留在镜像历史中:
- 在构建阶段生成配置后,用
RUN sed -i '/password/d' config/app.conf等命令脱敏,再复制到运行阶段 - 更稳妥方式:用
cat config.conf方式动态生成配置,不依赖外部文件 - 运行阶段镜像只
COPY --from=builder必要二进制或静态资源,绝不复制源码目录或原始配置模板
运行时注入优于构建时注入
真正安全的方案是让敏感信息“永远不进镜像”:
- 用Docker原生机制:通过
docker run -e DB_PASSWORD=xxx或docker-compose.yml中的environment:字段传入 - 生产环境优先使用
secrets(Docker Swarm)或external_secrets(K8s),避免明文出现在编排文件中 - 应用启动脚本应支持从
/run/secrets/读取(如cat /run/secrets/db_pass),而非读取镜像内嵌文件











