Compose常見問題

docker composedocker-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的歷史與發展

uprunstart 有什麼區別?

通常,你會使用 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 中使用 CMDENTRYPOINT 的 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-inittini)。這些封裝程式都可以正確處理 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 中的 COPYADD 指令將程式碼新增到映象中。這在你需要將程式碼與 Docker 映象一起遷移時很有用,例如將程式碼傳送到其他環境(生產、CI 等)時。

如果你想在開發程式碼時立即看到修改的效果(例如你的伺服器支援熱程式碼過載或即時過載),可以使用 volume

有些情況下你可能想同時使用這兩種方法。你可以使用 COPY 將程式碼包含在映象中,然後在開發期間使用 Compose 檔案中的 volume 來包含宿主機的程式碼。卷會覆蓋映象中的目錄內容。

頁面選項