關於 Docker Compose 的常見問題

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

uprunstart 有何區別?

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

如果您想對程式碼進行更改並立即看到它們反映出來,請使用 volume,例如在開發程式碼並且您的伺服器支援熱程式碼過載或即時過載時。

在某些情況下,您可能希望兩者都使用。您可以讓映象使用 COPY 包含程式碼,並在 Compose 檔案中使用 volume 在開發期間包含來自主機的程式碼。卷會覆蓋映象的目錄內容。