Compose常見問題
docker compose
和 docker-compose
之間有什麼區別?
Docker Compose命令列二進位制檔案的第一個版本於2014年釋出。它使用Python編寫,並透過 docker-compose
呼叫。通常,Compose V1專案在 compose.yaml 檔案中包含一個頂級的 version 元素,其值範圍從2.0到3.8,這些值引用特定的檔案格式。
Docker Compose命令列二進位制檔案的第二個版本於2020年宣佈,使用Go編寫,並透過 docker compose
呼叫。Compose V2忽略 compose.yaml 檔案中的頂級 version 元素。
更多資訊,請參閱Compose的歷史與發展。
up
、run
和 start
有什麼區別?
通常,你會使用 docker compose up
。使用 up
來啟動或重啟 compose.yaml
中定義的所有服務。在預設的“附加”(attached)模式下,你會看到所有容器的所有日誌。在“分離”(detached)模式 (-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 檔案中覆蓋了 command 或 entrypoint,不必擔心。如果可能,修改你正在執行的應用程式,為其新增一個顯式的
SIGTERM
訊號處理程式。將
stop_signal
設定為應用程式知道如何處理的訊號。services: web: build: . stop_signal: SIGINT
如果你無法修改應用程式,可以將應用程式封裝在一個輕量級的init系統(如 s6) 或訊號代理(如 dumb-init 或 tini)。這些封裝程式都可以正確處理
SIGTERM
。
如何在同一主機上執行Compose檔案的多個副本?
Compose 使用專案名稱為其所有容器和其他資源建立唯一識別符號。要執行一個專案的多個副本,可以使用 -p
命令列選項或 COMPOSE_PROJECT_NAME
環境變數設定一個自定義專案名稱。
我的Compose檔案可以使用JSON而不是YAML嗎?
是的。YAML 是 JSON 的超集,因此任何JSON檔案都應該是有效的YAML。要在Compose中使用JSON檔案,需要指定檔名,例如:
$ docker compose -f docker-compose.json up
我應該使用 COPY
/ADD
還是捲來包含我的程式碼?
你可以使用 Dockerfile 中的 COPY
或 ADD
指令將程式碼新增到映象中。這在你需要將程式碼與 Docker 映象一起遷移時很有用,例如將程式碼傳送到其他環境(生產、CI 等)時。
如果你想在開發程式碼時立即看到修改的效果(例如你的伺服器支援熱程式碼過載或即時過載),可以使用 volume
。
有些情況下你可能想同時使用這兩種方法。你可以使用 COPY
將程式碼包含在映象中,然後在開發期間使用 Compose 檔案中的 volume
來包含宿主機的程式碼。卷會覆蓋映象中的目錄內容。