敏感信息 Secret 管理
为什么需要 Secret 管理
在容器化应用中,敏感信息无处不在:数据库密码、API 密钥、TLS 证书、OAuth token 等。将它们硬编码在 Dockerfile、环境变量或源代码中是常见的安全漏洞。
不安全的做法
在 Dockerfile 中硬编码
# ❌ 绝对不要这样做
FROM node:18-alpine
ENV DB_PASSWORD=supersecret123
ENV API_KEY=sk-123456789
COPY . /app
CMD ["node", "app.js"]
密码会被包含在镜像层中,任何人都可以查看。
在 docker-compose.yml 中硬编码
# ❌ 不安全
services:
app:
image: myapp
environment:
- DB_PASSWORD=supersecret123
安全的 Secret 管理方式
方案一:使用环境变量文件(.env)
# .env(不要提交到 git)
DB_PASSWORD=supersecret123
API_KEY=sk-abcdefgh
JWT_SECRET=my-jwt-secret-2023
services:
app:
image: myapp
env_file:
- .env
方案二:使用 Docker Secrets(Swarm 模式)
# 创建 secret
echo "supersecret123" | docker secret create db_password -
# 在服务中使用
docker service create \
--name app \
--secret db_password \
myapp
Compose 中的 Secret 配置:
services:
app:
image: myapp
secrets:
- db_password
- api_key
secrets:
db_password:
external: true # 已经创建好的 secret
api_key:
file: ./api_key.txt # 从文件创建
容器内 secret 文件的默认路径:/run/secrets/
# 在应用代码中读取
cat /run/secrets/db_password
方案三:使用文件挂载
services:
app:
image: myapp
volumes:
- ./secrets/db_password.txt:/run/secrets/db_password:ro
- ./secrets/api_key.txt:/run/secrets/api_key:ro
方案四:运行时注入
# 使用环境变量(确保不保存在任何文件中)
export DB_PASSWORD=$(aws secretsmanager get-secret-value --secret-id db/password --query SecretString --output text)
docker compose up -d
方案五:使用专用密钥管理服务
# HashiCorp Vault
vault kv put secret/myapp db_password=supersecret123
# AWS Secrets Manager
aws secretsmanager create-secret --name db/password --secret-string supersecret123
# Azure Key Vault
az keyvault secret set --vault-name myvault --name db-password --value supersecret123
各语言读取 Secrets
Node.js
const fs = require('fs');
const dbPassword = fs.readFileSync('/run/secrets/db_password', 'utf8').trim();
Python
with open('/run/secrets/db_password', 'r') as f:
db_password = f.read().strip()
Java
import java.nio.file.*;
String dbPassword = Files.readString(Paths.get("/run/secrets/db_password")).trim();
Shell
DB_PASSWORD=$(cat /run/secrets/db_password)
生产中推荐方案:外部 Secret 管理
Vault Agent 注入
services:
app:
image: myapp
environment:
- VAULT_ADDR=http://vault:8200
volumes:
- vault-token:/home/appuser/.vault-token
vault-agent:
image: vault:latest
volumes:
- ./vault-agent-config.hcl:/etc/vault/agent.hcl
- vault-token:/home/vault/.vault-token
command: agent -config=/etc/vault/agent.hcl
Kubernetes External Secrets
apiVersion: 'kubernetes-client.io/v1'
kind: ExternalSecret
metadata:
name: db-password
spec:
backendType: secretsManager
data:
- key: db/password
name: db_password
BuildKit 的 Secret 支持
在 Dockerfile 构建过程中安全使用 secret:
# syntax=docker/dockerfile:1.4
FROM node:18-alpine
# 构建时注入 secret(不会留在镜像层中)
RUN --mount=type=secret,id=npmrc \
cat /run/secrets/npmrc > ~/.npmrc && \
npm ci && \
rm ~/.npmrc
COPY . .
CMD ["node", "app.js"]
# 构建时传递 secret
DOCKER_BUILDKIT=1 docker build --secret id=npmrc,src=.npmrc -t myapp .
.dockerignore 保护
# 确保敏感文件不会被复制到镜像中
.env
.env.*
secrets/
*.pem
*.key
**/credentials
最佳实践总结
| 场景 | 推荐做法 |
|---|---|
| 开发环境 | .env 文件(不提交 git) |
| 单机部署 | Docker Secrets(Swarm)或文件挂载 |
| 多机部署 | 外部密钥管理(Vault/AWS/等) |
| CI/CD | CI 系统的 secrets 管理功能 |
| Build 阶段 | BuildKit 的 –secret 参数 |
安全 checklist
- [ ] Dockerfile 中无硬编码 secret
- [ ] .env 文件在 .gitignore 中
- [ ] 使用 Docker Secrets 或外部密钥管理
- [ ] Secret 文件权限设置(chmod 600)
- [ ] 构建镜像时不包含 secret
- [ ] 定期轮换 secret
- [ ] Secret 访问有审计日志
敏感信息管理是容器安全的重要环节。正确的 secret 管理方案可以有效防止密码泄露、API 密钥被盗等安全事件。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容