使用 Docker Compose
Docker Compose 提供一種協調多個協同運作的容器的方式。範例包括處理要求的服務和前端網站,或使用輔助功能 (例如 Redis 快取) 的服務。如果您為應用程式開發使用微服務模型,則可以使用 Docker Compose 將應用程式程式碼分解為多個獨立執行的服務,這些服務使用 Web 要求進行通訊。本文可協助您為應用程式啟用 Docker Compose,無論應用程式是 Node.js、Python 還是 .NET,並協助您在 Visual Studio Code 中針對這些案例設定偵錯。
此外,對於單一容器案例,使用 Docker Compose 以獨立於工具的方式提供組態,這是單一 Dockerfile 無法做到的。容器的磁碟區掛載、連接埠對應和環境變數等組態設定可以在 docker-compose YML 檔案中宣告。
若要在 VS Code 中使用 Docker 擴充功能來使用 Docker Compose,您應該已熟悉 Docker Compose 的基本知識。
將 Docker Compose 支援新增至您的專案
如果您已有一個或多個 Dockerfile,您可以開啟命令選擇區 (⇧⌘P (Windows、Linux Ctrl+Shift+P)),然後使用Docker: 將 Docker Compose 檔案新增至工作區命令,即可新增 Docker Compose 檔案。依照提示操作。
您可以在開啟命令選擇區 (⇧⌘P (Windows、Linux Ctrl+Shift+P)) 並使用 Docker: 將 Docker 檔案新增至工作區 命令時,同時將 Docker Compose 檔案新增至您的工作區。系統會詢問您是否要新增 Docker Compose 檔案。如果您想要保留現有的 Dockerfile,請在系統提示您覆寫 Dockerfile 時選擇否。
Docker 擴充功能會將 docker-compose.yml
檔案新增至您的工作區。此檔案包含在生產環境中如預期般啟動容器的組態。在某些情況下,也會產生 docker-compose.debug.yml
。此檔案提供簡化的啟動模式,可啟用偵錯工具。
VS Code Docker 擴充功能會產生可立即運作的檔案,但您也可以自訂這些檔案,以針對您的案例進行最佳化。然後,您可以使用 Docker Compose Up 命令 (在 docker-compose.yml
檔案上按一下滑鼠右鍵,或在命令選擇區中尋找命令) 一次啟動所有項目。您也可以從 VS Code 中的命令提示字元或終端機視窗使用 docker-compose up
命令來啟動容器。請參閱 Docker Compose 文件,以瞭解如何設定 Docker Compose 行為,以及有哪些命令列選項可用。
使用 docker-compose 檔案,您現在可以在 docker-compose 檔案中指定連接埠對應,而不是在 .json 組態檔案中指定。如需範例,請參閱 Docker Compose 文件。
提示:使用 Docker Compose 時,請勿指定主機連接埠。相反地,讓 Docker 選取隨機可用的連接埠,以自動避免連接埠衝突問題。
將新的容器新增至您的專案
如果您想要新增另一個應用程式或服務,您可以再次執行將 Docker Compose 檔案新增至工作區,並選擇覆寫現有的 docker-compose 檔案,但您將遺失這些檔案中的任何自訂設定。如果您想要保留對 Compose 檔案的變更,您可以手動修改 docker-compose.yml
檔案以新增服務。通常,您可以複製現有的服務區段、貼上以建立新的項目,並視需要變更新服務的名稱。
您可以再次執行將 Docker 檔案新增至工作區命令,以產生新應用程式的 Dockerfile
。雖然每個應用程式或服務都有自己的 Dockerfile,但通常每個工作區會有一個 docker-compose.yml
檔案和一個 docker-compose.debug.yml
檔案。
在 Python 專案中,您的 Dockerfile
、.dockerignore
、docker-compose*.yml
檔案都位於工作區的根資料夾中。當您新增另一個應用程式或服務時,請將 Dockerfile 移至應用程式的資料夾中。
在 Node.js 專案中,Dockerfile
和 .dockerignore
檔案會位於該服務的 package.json
旁邊。
對於 .NET,資料夾結構已設定為在您建立 Docker Compose 檔案時處理多個專案,.dockerignore
和 docker-compose*.yml
會放在工作區根目錄中 (例如,如果專案位於 src/project1
中,則檔案位於 src
中),因此當您新增另一個服務時,您會在資料夾中建立另一個專案,例如 project2
,並依照先前所述重新建立或修改 docker-compose 檔案。
偵錯
首先,請參閱目標平台的偵錯文件,以瞭解在 VS Code 中使用容器偵錯的基本知識
如果您想要在 Docker Compose 中偵錯,請使用先前章節中所述的兩個 Docker Compose 檔案之一來執行 Docker Compose Up 命令,然後使用適當的附加啟動組態進行附加。直接使用一般啟動組態啟動不會使用 Docker Compose。
建立附加 啟動組態。這是 launch.json
中的一個區段。此程序大多是手動的,但在某些情況下,Docker 擴充功能可以透過新增預先設定的啟動組態來提供協助,您可以將其用作範本並進行自訂。以下章節說明每個平台 (Node.js、Python 和 .NET) 的程序。
Node.js
-
在偵錯索引標籤上,選擇組態下拉式清單,選擇新增組態,然後選取
Docker Attach
組態範本 Node.js Docker Attach (預覽)。 -
在
docker-compose.debug.yml
中設定偵錯連接埠。這會在您建立檔案時設定,因此您可能不需要變更它。在下列範例中,連接埠 9229 用於主機和容器上的偵錯。version: '3.4' services: node-hello: image: node-hello build: . environment: NODE_ENV: development ports: - 3000 - 9229:9229 command: node --inspect=0.0.0.0:9229 ./bin/www
-
如果您有多個應用程式,則需要變更其中一些應用程式的連接埠,以便每個應用程式都有唯一的連接埠。您可以在
launch.json
中指向正確的偵錯連接埠,並儲存檔案。如果您省略此步驟,系統會自動選擇連接埠。以下範例顯示 Node.js 啟動組態 - 附加
"configurations": [ { "type": "node", "request": "attach", "name": "Docker: Attach to Node", "remoteRoot": "/usr/src/app", "port": 9229 // Optional; otherwise inferred from the docker-compose.debug.yml. }, // ... ]
-
完成編輯附加組態後,儲存
launch.json
,然後選取新的啟動組態作為作用中組態。在偵錯索引標籤中,在組態下拉式清單中尋找新的組態。 -
在
docker-compose.debug.yml
檔案上按一下滑鼠右鍵,然後選擇 Compose Up。 -
當您附加至公開傳回 HTML 的 HTTP 端點的服務時,網頁瀏覽器不會自動開啟。若要在瀏覽器中開啟應用程式,請在側邊欄中選擇容器,按一下滑鼠右鍵,然後選擇在瀏覽器中開啟。如果設定了多個連接埠,系統會要求您選擇連接埠。
-
以一般方式啟動偵錯工具。從偵錯索引標籤中,選擇綠色箭頭 (啟動按鈕) 或使用 F5。
Python
若要使用 Docker Compose 偵錯 Python,請依照下列步驟執行
-
在偵錯索引標籤上,選擇組態下拉式清單,選擇新增組態,選擇 Python 偵錯工具,然後選取
Remote Attach
組態範本。 -
系統會提示您選擇要用於偵錯的主機 (例如,localhost) 和連接埠。Python 的預設偵錯連接埠為 5678。如果您有多個應用程式,則需要變更其中一個應用程式的連接埠,以便每個應用程式都有唯一的連接埠。您可以在
launch.json
中指向正確的偵錯連接埠,並儲存檔案。如果您省略此步驟,系統會自動選擇連接埠。"configurations": [ { "name": "Python Debugger: Remote Attach", "type": "debugpy", "request": "attach", "port": 5678, "host": "localhost", "pathMappings": [ { "localRoot": "${workspaceFolder}", "remoteRoot": "/app" } ] }
-
完成編輯附加組態後,儲存
launch.json
。瀏覽至偵錯索引標籤,然後選取 Python 偵錯工具:遠端附加作為作用中組態。 -
如果您已具有有效的 Dockerfile,我們建議執行 Docker: 將 Docker Compose 檔案新增至工作區 命令。這會建立
docker-compose.yml
檔案和docker-compose.debug.yml
,後者會磁碟區對應並在容器中啟動 Python 偵錯工具。如果您尚未具有 Dockerfile,我們建議執行 Docker: 將 Docker 檔案新增至工作區,然後選取是以包含 Docker Compose 檔案。注意:根據預設,當使用 Docker: 將 Docker 檔案新增至工作區時,選擇 Django 和 Flask 選項會為 Gunicorn 建立 Dockerfile 骨架。請依照 容器中的 Python 快速入門 中的指示,確保在繼續之前已正確設定。
-
在
docker-compose.debug.yml
檔案上按一下滑鼠右鍵 (如下所示範例),然後選擇 Compose Up。version: '3.4' services: pythonsamplevscodedjangotutorial: image: pythonsamplevscodedjangotutorial build: context: . dockerfile: ./Dockerfile command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 manage.py runserver 0.0.0.0:8000 --nothreading --noreload"] ports: - 8000:8000 - 5678:5678
-
容器建置並執行後,按下 F5,並選取 Python 偵錯工具:遠端附加 啟動組態,即可附加偵錯工具。
注意:如果您想要將 Python 偵錯工具匯入特定檔案,可以在 debugpy README 中找到更多資訊。
-
當您附加至公開 HTTP 端點並傳回 HTML 的服務時,網頁瀏覽器可能不會自動開啟。若要在瀏覽器中開啟應用程式,請在 Docker 瀏覽器中按一下滑鼠右鍵,然後選擇在瀏覽器中開啟。如果設定了多個連接埠,系統會要求您選擇連接埠。
您現在正在容器中偵錯正在執行的應用程式。
.NET
-
在偵錯索引標籤上,選擇組態下拉式清單,選擇新增組態,然後選取
Docker Attach
組態範本 .NET Core Docker Attach (預覽)。 -
VS Code 嘗試使用預設路徑,將
vsdbg
從主機複製到目標容器。您也可以在附加組態中提供現有vsdbg
執行個體的路徑。"netCore": { "debuggerPath": "/remote_debugger/vsdbg" }
-
完成編輯附加組態後,儲存
launch.json
,然後選取新的啟動組態作為作用中組態。在偵錯索引標籤中,在組態下拉式清單中尋找新的組態。 -
在
docker-compose.debug.yml
檔案上按一下滑鼠右鍵,然後選擇 Compose Up。 -
當您附加至公開傳回 HTML 的 HTTP 端點的服務時,網頁瀏覽器不會自動開啟。若要在瀏覽器中開啟應用程式,請在側邊欄中選擇容器,按一下滑鼠右鍵,然後選擇在瀏覽器中開啟。如果設定了多個連接埠,系統會要求您選擇連接埠。
-
以一般方式啟動偵錯工具。從偵錯索引標籤中,選擇綠色箭頭 (啟動按鈕) 或使用 F5。
-
如果您嘗試附加至在容器中執行的 .NET 應用程式,您會看到提示要求選取應用程式的容器。
若要略過此步驟,請在 launch.json 中附加組態中指定容器名稱
"containerName": "Your ContainerName"
接下來,系統會詢問您是否要將偵錯工具 (
vsdbg
) 複製到容器中。選擇是。
如果所有項目都已正確設定,偵錯工具應該會附加至您的 .NET 應用程式。
磁碟區掛載
根據預設,Docker 擴充功能不會針對偵錯組件執行任何磁碟區掛載。在 .NET 或 Node.js 中不需要這麼做,因為必要的組件已內建在執行階段中。如果您的應用程式需要磁碟區掛載,請使用 docker-compose*.yml
檔案中的 volumes
標籤來指定它們。
volumes:
- /host-folder-path:/container-folder-path
具有多個 Compose 檔案的 Docker Compose
工作區可以有多個 docker-compose 檔案,以處理不同的環境,例如開發、測試和生產環境。組態的內容可以分割成多個檔案。例如,定義所有環境通用資訊的基本 Compose 檔案,以及定義環境特定資訊的個別覆寫檔案。當這些檔案作為輸入傳遞至 docker-compose
命令時,它會將這些檔案合併為單一組態。根據預設,Docker: Compose Up 命令會傳遞單一檔案作為 Compose 命令的輸入,但您可以自訂 compose up
命令,以使用 命令自訂傳遞多個檔案。或者,您可以使用 自訂工作,以使用所需的參數叫用 docker-compose
命令。
注意:如果您的工作區具有
docker-compose.yml
和docker-compose.override.yml
,且沒有其他 Compose 檔案,則會叫用docker-compose
命令,且沒有輸入檔案,它會隱含地使用這些檔案。在此情況下,不需要自訂。
命令自訂
命令自訂提供各種方式,可根據您的需求自訂 compose up
命令。以下是 compose up
命令的一些範例命令自訂。
基本檔案和覆寫檔案
假設您的工作區具有基本 Compose 檔案 (docker-compose.yml
) 和每個環境的覆寫檔案 (docker-compose.dev.yml
、docker-compose.test.yml
和 docker-compose.prod.yml
),而且您一律使用基本檔案和覆寫檔案執行 docker compose up
。在此情況下,compose up
命令可以自訂,如下列範例所示。當叫用 compose up
命令時,${configurationFile}
會取代為選取的檔案。
"docker.commands.composeUp": [
{
"label": "override",
"template": "docker-compose -f docker-compose.yml ${configurationFile} up -d --build",
}
]
範本比對
假設您每個環境都有一組不同的輸入檔案。您可以定義具有規則運算式比對的多個範本,選取的檔案名稱會根據此 match
屬性進行比對,並使用對應的範本。
"docker.commands.composeUp": [
{
"label": "dev-match",
"template": "docker-compose -f docker-compose.yml -f docker-compose.debug.yml -f docker-compose.dev.yml up -d --build",
"match": "dev"
},
{
"label": "test-match",
"template": "docker-compose -f docker-compose.yml -f docker-compose.debug.yml -f docker-compose.test.yml up -d --build",
"match": "test"
},
{
"label": "prod-match",
"template": "docker-compose -f docker-compose.yml -f docker-compose.release.yml -f docker-compose.prod.yml up -d --build",
"match": "prod"
}
]
在叫用命令時挑選範本
如果您從命令範本中省略 match
屬性,則每次叫用 compose up
命令時,系統都會詢問您要使用哪個範本。例如
"docker.commands.composeUp": [
{
"label": "dev",
"template": "docker-compose -f docker-compose.yml -f docker-compose.common.dev.yml ${configurationFile} up -d --build"
},
{
"label": "test",
"template": "docker-compose -f docker-compose.yml -f docker-compose.common.test.yml ${configurationFile} up -d --build"
},
{
"label": "prod",
"template": "docker-compose -f docker-compose.yml -f docker-compose.common.prod.yml ${configurationFile} up -d --build"
},
],
自訂工作
除了使用命令自訂之外,您也可以定義如下的工作來叫用 docker-compose
命令。如需此選項的詳細資訊,請參閱 自訂工作。
{
"type": "shell",
"label": "compose-up-dev",
"command": "docker-compose -f docker-compose.yml -f docker-compose.Common.yml -f docker-compose.dev.yml up -d --build",
"presentation": {
"reveal": "always",
"panel": "new"
}
}