真正安全的做法是运行时解密注入,而非明文存储;应使用外部加密工具预处理配置、docker secrets挂载、buildkit构建密钥隔离,或对接vault/kms动态拉取。
敏感信息不能直接明文写进环境变量文件或 compose 配置里。真正安全的做法是把加密逻辑和密钥管理分离,让敏感值在运行时才解密注入,而不是以明文形式存在于配置中。
用外部加密工具预处理配置文件
把数据库密码、API 密钥等敏感字段先用 age 或 openssl 加密成二进制或 Base64 字符串,存入配置文件(如 config.enc)。容器启动时,在 entrypoint 脚本里调用解密命令,再把解密后的内容赋给环境变量:
- 构建镜像时只安装
age或openssl,不带任何密钥 - 密钥通过 Docker Secrets(Swarm)或 CI/CD 安全变量传入容器
- entrypoint 中执行:
export DB_PASSWORD="$(age -d -i /run/secrets/db_key config.enc 2>/dev/null)"
用 Docker Secrets 替代环境变量传递
Docker Swarm 模式下,secrets 是专为敏感数据设计的机制,不会出现在进程列表、镜像层或日志中:
- 定义 secret:
echo "myprodpass" | docker secret create db_password - - 在 Compose 文件中挂载:
secrets: - db_password - 容器内自动映射到
/run/secrets/db_password,应用读取该路径即可
构建阶段用 BuildKit Secret 避免密钥进入镜像
如果敏感信息仅用于构建(比如拉私有依赖的 token),绝不能用 build-arg——它会留在镜像历史里。改用 --secret:
- Dockerfile 中写:
RUN --mount=type=secret,id=npm_token cat /run/secrets/npm_token > .npmrc - 构建命令:
docker compose build --secret id=npm_token,src=./.npm-token - 构建完成后,
.npmrc和密钥都不会保留在最终镜像中
结合 Vault 或 KMS 动态注入
在生产环境中,推荐对接 HashiCorp Vault、AWS Secrets Manager 等服务:
- 容器启动时,用轻量客户端(如
vault kv get)按需拉取解密后的值 - 配合短期 Token 和最小权限策略,避免长期凭证泄露风险
- 可与 init 容器配合:init 容器获取密钥 → 写入共享 volume → 主应用读取











