目标: 在 Docker / Compose 环境中安全管理密钥(密码、Token、API Key),按推荐度从高到低整理三种方案。
🥇 方案一:Docker Secrets(Swarm / Compose v2.23+)
定位: 最安全的原生方案。密钥以文件形式挂载到容器内存文件系统(tmpfs),不经过环境变量。
Compose 示例(docker-compose.yml)
services:
app:
image: myapp:latest
secrets:
- db_password
- api_key
secrets:
db_password:
file: ./secrets/db_password.txt # 本地文件,加入 .gitignore
api_key:
environment: API_KEY # Compose 2.23+:可从宿主机 ENV 注入为 secret
应用侧读取(Python 示例:读文件而非 ENV)
with open('/run/secrets/db_password', 'r') as f:
db_password = f.read().strip()
优点
- 不落盘(运行时挂载到 tmpfs)
- 不暴露在
docker inspect中 - 不继承给子进程(相较把密钥放进环境变量更安全)
缺点 / 约束
- 需要应用支持"从文件读取密钥"
- 旧版 Compose 可能不支持(尤其是
environment:注入 secret 的能力)
🥈 方案二:外部密钥管理器 + 运行时注入
定位: 生产环境常见首选。密钥存放在专用 Secret Manager 中,容器启动时动态获取并注入(通常写入共享 tmpfs 卷或以挂载形式提供)。
常见实现
- HashiCorp Vault Agent:Sidecar 模式拉取密钥,写入共享 tmpfs 卷
- Infisical / Doppler:面向容器/应用的密钥同步与注入工具
- 云厂商 CSI Driver:将云 Secret Manager 直接以卷形式挂载到 Pod/容器(常用于 K8s 场景)
优点
- 密钥集中管理(审计、轮换、权限控制更完善)
- 运行时获取(降低配置泄露风险)
注意点
- 需要引入额外组件/依赖(Agent、Sidecar、网络访问、权限配置)
- 要设计好密钥轮换与应用重载策略
🥉 方案三:.env 文件 + 严格防护(最低可接受标准)
定位: 如果必须使用环境变量,至少做到"密钥不写死在 compose yml 中",改用独立 .env 文件并加强防护。
Compose 示例(使用 env_file)
services:
app:
env_file:
- .env.production # ✅ 使用独立文件,避免把密钥写死在 yml 中
必须配套的防护措施(检查清单)
| 措施 | 命令 / 操作 |
|---|---|
| Git 忽略 | 在 .gitignore 中添加:.env* |
| 文件权限 | chmod 600 .env.production |
| 禁止构建时写入 | Dockerfile 仅用 ARG 传递非敏感值;不要用 ENV 存密钥 |
| 限制 Docker 访问 | 严格控制 /var/run/docker.sock 挂载与 docker 组用户 |
| 日志脱敏 | 确保应用不打印启动时环境变量 dump(避免密钥进入日志) |
| 只读根文件系统 | 启用 read_only: true,并用 tmpfs 挂载 /tmp |
快速选型建议
- 能用 Docker Secrets 就优先用(最少暴露面)
- 生产环境优先考虑外部密钥管理器(审计、轮换、权限最完善)
.env仅作为兜底,并严格执行上面的防护清单

