Docker Compose 的 secrets 机制通过将敏感信息以只读文件形式挂载到 /run/secrets/<name>,比环境变量更安全;需在顶层声明 secrets(支持 file/external/inline),服务中挂载并由应用主动读取文件内容,更新需重建服务。

直接在 docker-compose.yml 中用 secrets 声明并挂载敏感凭证,是比环境变量更底层、更隔离的安全方式——它不把密码写进镜像、不暴露在进程环境、也不随日志或元数据泄露。核心逻辑是:Docker 在容器启动时,把密钥以只读文件形式挂载到 /run/secrets/<name>,应用代码主动读取该文件内容。
一、正确声明 secrets 块(顶层配置)
在 docker-compose.yml 文件最外层定义 secrets:,支持三种来源:
-
本地文件(生产推荐):如
db_password: file: ./secrets/db-pass.txt,该文件不能提交到 Git,需加进.gitignore,且权限设为600 -
外部 secret(Swarm 场景):如
tls_cert: external: true,表示复用已通过docker secret create创建的 secret -
内联值(仅限开发测试):如
debug_key: driver_opts: { "value": "dev123" },禁止用于生产环境
二、在服务中挂载指定 secret
在 services.<service-name>.secrets: 下列出该服务可访问的 secret 名称,并可自定义挂载细节:
- 基础写法:
- db_password→ 默认挂载为/run/secrets/db_password - 自定义路径:
- source: db_password target: /run/secrets/passwd - 控制权限:
- source: db_password uid: 1001 gid: 1001 mode: 0400(避免因默认0444导致某些应用拒绝读取)
注意:一个 secret 可被多个服务同时挂载,无需重复定义。
三、应用代码读取 secret 文件(不是环境变量)
容器内必须打开并读取文件,而非依赖环境变量。常见语言示例:
-
Shell:
DB_PASS=$(cat /run/secrets/db_password | tr -d '\n\r')(建议去除换行) -
Python:
with open('/run/secrets/db_password') as f: password = f.read().strip() -
PHP:
$password = trim(file_get_contents('/run/secrets/db_password'));
特别提醒:PostgreSQL、MySQL、Nextcloud 等主流镜像原生支持 _FILE 后缀变量(如 POSTGRES_PASSWORD_FILE),设置后会自动读取对应 secret 文件,无需改应用代码。
四、关键注意事项与避坑点
- Secret 文件内容应为纯文本,无 BOM、无多余空格或换行;可用
echo -n "mypassword" > ./secrets/db-pass.txt生成 - 若服务设了
read_only: true,则只能使用file:类型 secret,不能用external或内联 - 相对路径的
target:会被自动补前缀为/run/secrets/,例如target: app/pass实际挂载为/run/secrets/app/pass - 更新 secret 需重建服务:先
docker compose down,再更新文件内容,最后docker compose up -d


















