1134 字
6 分鐘

Docker Compose 改了環境變數沒生效?restart 不會重建容器

改完 .envcompose.yaml 後執行 docker compose restart web,container 裡的環境變數卻還是舊值,這不是 Docker 沒讀到檔案,而是指令做的事情比想像中單純。

Docker 官方文件明確寫出:docker compose restart 只重啟既有 service container;Compose 設定變更,包括環境變數,不會在這個動作中更新。要讓新值進入 container,應先驗證 Compose 解析結果,再用 docker compose up 讓它重新建立服務。

restart 為什麼不會讀回新設定?#

Container 建立時,Compose 會把 environmentenv_file 的值寫進該 container 的執行設定。restart 只停止並重新啟動這個既有 container,不會重新建立一份新的設定。

例如:

services:
web:
image: alpine:3.22
command: ['sh', '-c', 'while true; do sleep 3600; done']
environment:
APP_MODE: ${APP_MODE:?請先設定 APP_MODE}

第一次以 APP_MODE=staging 建立 container 後,即使你把 .env 改成 APP_MODE=production,下面的指令也不會把新值寫進既有 container:

Terminal window
docker compose restart web
docker compose exec web printenv APP_MODE

restart 適合處理程序卡住、需要重新載入已存在的 runtime 設定,或只想重啟服務的情境;它不是設定變更的部署指令。

先看 Compose 實際解析到什麼值#

在重建前,先確認你執行命令的工作目錄、Compose 檔案與環境檔都和正式流程相同:

Terminal window
docker compose config --environment
docker compose config
docker compose ps

docker compose config --environment 會列出 Compose 用來做插值的環境;docker compose config 則會 render 出準備送給 Docker Engine 的 model。兩個輸出都可能包含敏感資料,CI log 只保留非敏感欄位。

如果你把 env_file${VAR} 混在同一份設定裡,先看 Docker Compose 的 env_file 與變數插值差異。service 的 env_file 是提供 container runtime environment,.env、shell 或 CLI --env-file 則可能是 Compose 解析 ${VAR} 的來源。

up 重新建立 container#

設定已變更,讓 Compose 自動判斷#

Docker 官方的 up 行為是:如果 service 設定或 image 在 container 建立後改變,Compose 會停止並重新建立 container:

Terminal window
docker compose up -d web

掛載的 named volume 會沿用;這和刪除 volume 是不同的動作。

想明確保證重建時使用 --force-recreate#

如果你正在排查「設定到底有沒有套用」的問題,使用明確的指令比較容易留下可讀的部署紀錄:

Terminal window
docker compose up -d --force-recreate web

若 image 內容也變更,例如 Dockerfile 或 build context 已更新,再加上 --build

Terminal window
docker compose up -d --build --force-recreate web

只想處理 web、不想讓相依服務跟著被操作時,可以加 --no-deps。但先確認 app 真的能連到現有的 dependency,不要為了縮小指令範圍而跳過必要的健康檢查。

新值仍沒出現時,沿著這四層檢查#

  1. Compose 來源:shell、CLI --env-file、project .env 與 service env_file 不是同一層,優先順序也不同。
  2. 實際 service:確認你重建的是正確的 project、service 名稱與 -f 檔案組合。
  3. container 值:用 docker compose exec web printenv APP_MODE 看 container 真正拿到什麼,而不是只看主機上的 .env
  4. 程式啟動時機:有些程式只在 process 啟動時讀取環境變數;container 已重建後,才算讓程式重新取得新值。

不要為了更新環境變數直接執行 docker compose down -v-v 會移除 volume,資料庫或上傳檔案可能因此失去可還原的儲存。設定變更通常只需要針對正確 service 執行 up 和 recreate。

run -e 不是 service 的長期設定#

docker compose run -e 適合一次性的 command 或 migration,不會改寫 compose.yaml,也不會更新已經由 up 建立的 service container:

Terminal window
docker compose run --rm -e APP_MODE=maintenance web sh -c 'printenv APP_MODE'

若你要讓下一次部署仍使用同一個值,應把來源放在清楚的 Compose 設定或指定的 --env-file,再用 configup 驗證。不要把一次性的 run 結果當成 service 已經換環境。

常見問題#

Q: 改了 .env 後,應該用 restart 還是 up#

A: 改了會進入 container 的環境變數,使用 docker compose up -d service,需要明確重建時加 --force-recreaterestart 只重啟既有 container,不會更新 Compose 設定。

Q: 只改環境變數也需要 --build 嗎?#

A: 不一定。只改 Compose 的 environment source 時,通常重建 container 就足夠;只有 image 內容、Dockerfile 或 build context 也變更時,才需要考慮 --build

Q: up 重建 container 會刪掉資料嗎?#

A: Compose 會保留掛載的 volume,但不要把這個行為延伸成「所有資料都安全」。先確認資料是 named volume、bind mount 還是 container writable layer,也不要在只是更新環境變數時使用 down -v

參考資料:

Docker Docs:docker compose restart

Docker Docs:docker compose up

Docker Docs:docker compose config

Docker Docs:Environment variables precedence in Docker Compose

Docker Compose 改了環境變數沒生效?restart 不會重建容器
https://laplusda.com/posts/docker-compose-restart-environment-not-updated/
作者
Zero
發佈於
2026-08-22
許可協議
CC BY-NC-SA 4.0
這篇文章有幫助嗎?

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