關於 Docker Compose 的常見問題
docker compose
與 docker-compose
有何區別?
Docker Compose 命令列二進位制檔案的版本一於 2014 年首次釋出。它用 Python 編寫,並透過 docker-compose
呼叫。通常,Compose v1 專案在 compose.yaml
檔案中包含一個頂級版本元素,其值範圍從 2.0 到 3.8,指代特定的檔案格式。
Docker Compose 命令列二進位制檔案的版本二於 2020 年宣佈,它用 Go 編寫,並透過 docker compose
呼叫。Compose v2 忽略 compose.yaml 檔案中的版本頂級元素。
欲瞭解更多資訊,請參閱 Compose 的歷史與發展。
up
、run
和 start
有何區別?
通常,你會使用 docker compose up
。使用 up
來啟動或重新啟動 compose.yaml
中定義的所有服務。在預設的“附加”模式下,你會看到所有容器的所有日誌。在“分離”模式(-d
)下,Compose 在啟動容器後退出,但容器會繼續在後臺執行。
docker compose run
命令用於執行“一次性”或“臨時”任務。它需要你想要執行的服務名稱,並且只啟動執行服務所依賴的服務容器。使用 run
來執行測試或執行管理任務,例如從資料卷容器中刪除或新增資料。run
命令的行為類似於 docker run -ti
,因為它會開啟一個互動式終端到容器,並返回與容器中程序的退出狀態匹配的退出狀態。
docker compose start
命令僅用於重新啟動之前建立但已停止的容器。它從不建立新容器。
為什麼我的服務需要 10 秒才能重新建立或停止?
docker compose stop
命令嘗試透過傳送 SIGTERM
來停止容器。然後它會等待 預設超時 10 秒。超時後,會向容器傳送 SIGKILL
以強制終止它。如果你正在等待此超時,這意味著你的容器在收到 SIGTERM
訊號時沒有關閉。
關於容器中程序處理訊號的問題已經有很多文章。
要解決此問題,請嘗試以下操作:
確保你在 Dockerfile 中使用
CMD
和ENTRYPOINT
的 exec 形式。例如,使用
["program", "arg1", "arg2"]
而不是"program arg1 arg2"
。使用字串形式會導致 Docker 使用bash
執行你的程序,而bash
無法正確處理訊號。Compose 始終使用 JSON 形式,因此如果你在 Compose 檔案中覆蓋了命令或入口點,請不用擔心。如果可能,修改你正在執行的應用程式,為
SIGTERM
新增一個顯式訊號處理器。將
stop_signal
設定為應用程式知道如何處理的訊號。services: web: build: . stop_signal: SIGINT
如果無法修改應用程式,請將應用程式包裝在一個輕量級 init 系統(如 s6)或訊號代理(如 dumb-init 或 tini)中。這些包裝器都可以妥善處理
SIGTERM
。
如何在同一主機上執行多個 Compose 檔案副本?
Compose 使用專案名稱為專案的所有容器和其他資源建立唯一的識別符號。要執行專案的多個副本,請使用 -p
命令列選項或 COMPOSE_PROJECT_NAME
環境變數 設定自定義專案名稱。
我可以使用 JSON 而不是 YAML 作為我的 Compose 檔案嗎?
是的。YAML 是 JSON 的超集,因此任何 JSON 檔案都應該是有效的 YAML。要將 JSON 檔案與 Compose 一起使用,請指定要使用的檔名,例如:
$ docker compose -f compose.json up
我應該使用 COPY
/ADD
還是捲來包含我的程式碼?
您可以使用 Dockerfile
中的 COPY
或 ADD
指令將程式碼新增到映象中。這在您需要將程式碼與 Docker 映象一起重新定位時很有用,例如在將程式碼傳送到其他環境(生產、CI 等)時。
如果您想對程式碼進行更改並立即看到它們反映出來,請使用 volume
,例如在開發程式碼並且您的伺服器支援熱程式碼過載或即時過載時。
在某些情況下,您可能希望兩者都使用。您可以讓映象使用 COPY
包含程式碼,並在 Compose 檔案中使用 volume
在開發期間包含來自主機的程式碼。卷會覆蓋映象的目錄內容。