1591 字
8 分鐘

Docker Compose secrets 與 configs 怎麼選?從環境變數改成檔案掛載

Docker Compose 裡的 environment 很方便,但把密碼、API key 或憑證直接放進環境變數,會讓所有能讀取 process environment 的程式都更容易碰到它,也可能在 debug log 或錯誤診斷中被印出。Compose 的 secretsconfigs 都能把資料掛成檔案,但用途並不相同。

直接答案是:敏感資料用 secrets,一般執行期設定用 configs,非敏感的簡單開關才用 environment;建置期間才需要的 credential 則用 build secret。 這些欄位都要求 service 明確授權,且本機 file: 來源仍受 host 檔案權限與 Compose trust model 影響,不是自動加密的秘密保管庫。

先分清四種設定邊界#

方式生命週期容器內的形態適合放什麼不要拿來做什麼
environmentruntime環境變數非敏感設定、*_FILE 路徑密碼、私鑰、長期 token
service secretsruntime/run/secrets/<name> 唯讀檔案密碼、API key、憑證可公開的完整設定檔
service configsruntime預設掛在 /<name> 的檔案nginx、feature flag、一般設定需要保密的 credential
build.secretsbuild timeDockerfile 指令的 temporary mount私有 npm registry、SSH、建置 tokenruntime 應用程式設定

secretsconfigs 的名稱先在 Compose 頂層宣告,再由每個 service 的同名欄位明確 grant。只宣告 secrets 不會讓所有服務自動看得到它;這個預設阻擋了「新增一個 secret 後整個 Compose project 都能讀」的錯誤假設。

最小的 runtime secrets 與 configs 範例#

下面的例子讓 api 同時取得資料庫密碼和一般設定檔:

services:
api:
image: ghcr.io/example/api:1.0
environment:
APP_CONFIG_FILE: /etc/myapp/app.conf
DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
configs:
- source: app_config
target: /etc/myapp/app.conf
secrets:
db_password:
file: ./secrets/db_password.txt
configs:
app_config:
file: ./config/app.conf

啟動後,Compose 只把 db_password 掛到這個 service 的 /run/secrets/db_passwordapp_config 則掛到指定的 /etc/myapp/app.confDB_PASSWORD_FILE 不是 Compose 的特殊語法,它只有在映像內的應用程式或官方映像支援 _FILE 慣例時才會真的讀取該檔案。若程式只接受 DB_PASSWORD,應修改程式的啟動邏輯,而不是把秘密再複製回 environment。

如果不需要自訂路徑,也可以用短語法:

services:
api:
secrets:
- db_password
configs:
- app_config

短語法會使用資源名稱作為容器內的檔名。Linux container 的 config 預設路徑是 /<config-name>;secret 則是 /run/secrets/<secret_name>。需要讓既有程式使用固定路徑時,改用上面的 long syntax 明確寫 target

secretsconfigs 真正的差別#

Docker 文件把 secret 定義成不應放進 Dockerfile、source code 或未加密儲存的敏感資料;Compose 以檔案方式提供它,並用 service-level grant 限制可見範圍。Config 也會以檔案掛載,但目的只是讓 service 不必重建 image 就能換一般設定,預設檔案權限可能是 world-readable 0444

因此不要只因為兩者都「掛成檔案」就混用:

  • app.conf 如果包含 host、port、feature flag 或公開的服務設定,可以放 configs
  • db_password.txt、OAuth client secret、TLS private key 或 registry token 應放 secrets
  • 一份混合檔案同時包含公開設定和秘密時,最好拆成兩個輸入,讓 service 只取得實際需要的部分。
  • 需要在 image build 階段登入私有 registry 時,請看 Docker Build secrets 與 ARG、ENV 的差異,不要把 build secret 誤當成啟動後的 runtime secret。

file: 不代表本機 secret 已被加密#

本機 Compose 常見的 file: 寫法,實際上仍會由執行 Compose 的使用者讀取 host 檔案。Docker 的 trust model 也提醒,secretsconfigsfile:env_fileinclude 等欄位會讀取 host 可存取的內容,內容還可能在 Compose 載入或 docker compose config 輸出時出現。

這表示要同時做三件事:

  1. ./secrets/ 放進 .gitignore,並用最小的 host 檔案權限限制誰可以讀。
  2. 不要在公開 CI log 執行會把完整 model 印出來的 docker compose config;要驗證語法時優先用 docker compose config -q
  3. 在 production 優先使用平台已建立的 external secret/config,或由部署平台在啟動時注入,而不是把正式 secret file 放在 application repository。

external: true 的意思是 Compose 不負責建立資源,會向 container platform 查找既有名稱;找不到就失敗。它能把資源生命週期交給平台,但不等於你已經確認平台的加密、備份、權限與 rotation policy,這些仍要另外驗證。

啟動前做不洩漏內容的驗證#

先檢查 Compose model 是否能解析:

Terminal window
docker compose config -q

接著在不輸出 secret 內容的前提下,確認路徑與可讀性:

Terminal window
docker compose run --rm api sh -eu -c '
test -r /run/secrets/db_password
test -r /etc/myapp/app.conf
printf "%s\n" "runtime files are readable"
'

如果 service 看不到檔案,按這個順序查:

  1. top-level 名稱是否和 service grant 完全一致。
  2. source 是否引用了實際存在的 secret/config。
  3. long syntax 的 target 是否和應用程式啟動參數相同。
  4. container user 是否具備讀取掛載檔案的權限;不要為了快速通過而把整個容器改成 privileged。
  5. 這份 Compose 是否由另一個 -f override 合併,意外移除了 secrets 或 configs。

這和 Docker Compose include 拆分設定檔時的路徑問題是同一種排錯習慣:先看 Compose 最終解析出的 model,再看容器內的實際 mount,不要只讀單一 YAML 檔猜測。

結論是:secrets 解決的是 runtime credential 的傳遞邊界,configs 解決的是不必重建 image 的一般設定;兩者都不能代替 secret manager,也不能抵消 host、Compose CLI、容器內程式與 log 的存取風險。先依資料敏感度拆分,再用 explicit grant 和不洩漏內容的檢查命令驗證,才是可維護的 Compose 設計。

常見問題#

configs 可以拿來放資料庫密碼嗎?#

不建議。Configs 的目的是一般執行期設定,預設掛載檔案權限也可能較寬;密碼、token 與 private key 應使用 secrets,並確認外部平台的保存與輪替方式。

Compose secrets 會自動把 secret 加密嗎?#

不能一概而論。Compose 會依 fileenvironmentexternal 來源取得資料;本機 file: 仍讀取 host 檔案,安全性取決於 host 權限與執行環境。不要把 Compose YAML 裡的 secrets 宣告當成加密保管庫。

為什麼 DB_PASSWORD_FILE 設了卻沒有作用?#

_FILE 是許多映像採用的慣例,不是 Compose 自動解析的欄位。先看該映像的文件或 entrypoint 是否會讀取 /run/secrets/db_password;若沒有,就在應用程式啟動邏輯中支援檔案輸入,避免把內容轉回 environment。

參考資料:

Docker Docs:Manage secrets securely in Docker Compose

Docker Docs:Configs top-level element

Docker Docs:Trust model for Compose files

Docker Compose secrets 與 configs 怎麼選?從環境變數改成檔案掛載
https://laplusda.com/posts/docker-compose-secrets-configs-runtime/
作者
Zero
發佈於
2026-08-30
許可協議
CC BY-NC-SA 4.0
這篇文章有幫助嗎?

回報錯字、失效連結,或告訴我你想看的延伸主題。