安全存放敏感数据的关键是构建隔离与控制机制:绝不硬编码密钥进镜像,禁用--build-arg传密钥,优先使用docker secrets(swarm)、tmpfs+初始化脚本(单机)或宿主机加密卷(持久化),配合.dockerignore和多阶段构建。

安全存放敏感数据,关键不是选什么存储驱动,而是构建一层层隔离和控制机制。Overlay2 本身不加密也不鉴权,但它提供了支撑能力——比如只读挂载、内存临时文件系统、用户命名空间映射。真正起作用的是你在它之上怎么配置运行时行为。
绝不让密钥进镜像
这是最基础也最容易踩坑的一条。任何密码、证书、API Key 都不能通过 COPY、ADD 或 --build-arg 写入镜像层。一旦进入镜像,就可能被 docker history 查看、被导出传播、被误推送到公开仓库。
- 用
.dockerignore明确排除.env、secrets/、*.pem、config/*.yaml等路径 - 采用多阶段构建:构建阶段编译打包,运行阶段只复制二进制或 dist 目录,完全跳过配置和密钥文件
- 禁止用
docker build --build-arg KEY=xxx传密钥——build-args 会保留在镜像历史中
Swarm 场景优先用 Docker Secrets
如果你在 Swarm 集群中部署服务,Docker Secrets 是原生、开箱即用的安全方案。它把密钥加密后存在 Raft 日志里,节点间通信强制 TLS,容器内以只读文件形式挂载到 /run/secrets/,不落盘、不进镜像、重启即清空。
- 创建:
echo "my-db-pass" | docker secret create db_password - - 挂载到服务:
docker service create --name app --secret db_password nginx:alpine - 容器内自动可见为
/run/secrets/db_password,权限默认0444,应用需以只读方式打开
单机环境用 tmpfs + 初始化脚本
没有 Swarm?那就用 --tmpfs 模拟 Secrets 的效果。它把指定目录挂载为内存文件系统,内容不写磁盘、重启即失,再配合初始化逻辑注入密钥。
- 启动时加参数:
docker run --tmpfs /run/secrets:rw,noexec,nosuid,size=8m myapp - 容器启动后,由 entrypoint 脚本从 Vault、host-mounted 加密卷或 GPG 解密后的文件中读取密钥,写入
/run/secrets/ - 确保应用打开文件时使用
O_RDONLY,并检查文件权限是否为0400或0440
持久化密钥用宿主机级加密
如果某些密钥必须长期保存(比如数据库主密钥),不要放在容器里管理。应该交由宿主机操作系统处理:
- 用 LUKS 加密块设备或 VeraCrypt 卷,在宿主机上挂载为
/mnt/encrypted - 再以只读方式绑定挂载进容器:
docker run -v /mnt/encrypted:/keys:ro myapp - Docker 不参与解密过程,只传递已解密的文件句柄,责任边界清晰,风险可控











