多阶段构建是docker镜像安全加固最直接有效的手段,通过分离构建与运行环境,彻底移除编译器、源码、敏感文件等高风险内容,仅保留运行必需产物;结合alpine或scratch基础镜像、精确copy路径、非root用户及只读文件系统,显著压缩攻击面。

多阶段构建是 Docker 镜像安全加固中最直接、最有效的手段之一。它不是锦上添花的优化技巧,而是从源头切断代码泄露、工具残留和攻击面扩大的关键设计。
分离构建与运行环境,彻底移除敏感内容
传统单阶段构建会把编译器、调试工具、源代码、日志、临时文件甚至 .git 目录一并打包进最终镜像,一旦镜像被拉取或误暴露,极易导致源码泄露或凭证外泄。多阶段构建通过明确划分阶段,让这些高风险内容只存在于中间构建容器中,且不会写入最终层。
- 构建阶段(builder)使用完整开发镜像(如
node:18或golang:1.24),完成依赖安装、代码编译、测试打包 - 运行阶段(runtime)切换为极简镜像(如
alpine:latest或scratch),仅用COPY --from=builder复制编译产物(如/app/dist、/app/myapp) - 不复制
src/、node_modules/(除非必须)、.env.example、Dockerfile等非运行必需项
精简基础镜像,压缩漏洞暴露面
最终镜像体积越小,包含的系统组件越少,潜在可利用的漏洞就越有限。Alpine 镜像约 5MB,而 Ubuntu 镜像常超 100MB,前者默认不含 bash、netstat、lsof 等调试工具,攻击者难以横向渗透或提权。
- 优先选用官方 Alpine 变体(如
python:3.11-alpine、node:18-alpine) - 对静态编译语言(Go、Rust),可进一步使用
scratch镜像,实现“零操作系统”运行 - 避免在运行阶段执行
apk add或apt-get install,防止引入未审计的包
显式控制复制路径,杜绝意外泄露
COPY --from 指令若不加限制,可能把构建阶段的整个工作目录都带入运行镜像。必须精确指定目标文件或子目录,拒绝通配符泛复制。
- ✅ 正确:
COPY --from=builder /app/dist ./dist - ❌ 危险:
COPY --from=builder /app .(可能带入src/、secrets/、build.log) - 构建阶段中提前清理敏感文件:如
RUN rm -f .env.local *.key *.pem - 敏感配置(如数据库密码)绝不写入镜像,应通过环境变量或挂载 Secret 方式注入
权限最小化,限制容器运行时能力
即使镜像本身干净,以 root 用户运行仍存在提权风险。多阶段构建可自然融入权限隔离策略。
- 运行阶段添加非 root 用户:
RUN adduser -D appuser && chown -R appuser:appuser /app - 切换用户执行:
USER appuser,确保进程无权修改系统目录或读取宿主机敏感路径 - 结合
docker run --read-only和--tmpfs进一步限制写操作范围











