教學課程:使用 Docker Compose 建立多容器應用程式

在本教學課程中,您將會了解如何在 Visual Studio 中使用容器工具管理多個容器並在容器之間通訊。 管理多個容器需要容器協調流程,而且需要 Docker Compose 或 Service Fabric 之類的協調器。 針對這些程序,您可以使用 Docker Compose。 Docker Compose 很適合用來在開發週期期間進行本機偵錯和測試。

您將在本教學課程中建立的完整範例可在 GitHub 上找到,其位於 https://github.com/MicrosoftDocs/vs-tutorial-samplesdocker/ComposeSample 資料夾。

必要條件

  • Docker Desktop
  • 已安裝網頁程式開發Azure Tools 工作負載和/或 .NET 跨平台開發工作負載的 Visual Studio 2022。 此安裝包含 .NET 8 開發工具。

建立 Web 應用程式專案

在 Visual Studio Code 中建立名為 WebFrontEndASP.NET Core Web 應用程式專案,以建立具有 Razor 頁面的 Web 應用程式。

Screenshot showing Create ASP.NET Core Web App project.

請勿選取 [啟用 Docker 支援]。 您稍後會在程序中新增 Docker 支援。

Screenshot of the Additional information screen when creating a web project. The option to Enable Docker Support is not selected.

注意

在 Visual Studio 2022 17.2 與更新版本中,您可以改為針對此專案使用 Azure Functions。

Screenshot showing Create ASP.NET Core Web App project.

請勿選取 [啟用 Docker 支援]。 您稍後會在程序中新增 Docker 支援。

Screenshot of the Additional information screen when creating a web project. The option to Enable Docker Support is not selected.

建立 Web API 專案

將專案新增至相同的解決方案,並將其命名為 MyWebAPI。 選取 [API] 作為專案類型,並清除 [針對 HTTPS 進行設定] 的核取方塊。 在此設計中,我們僅將 SSL 用於與用戶端之間的通訊,而不是用於相同 Web 應用程式中的容器之間的通訊。 只有 WebFrontEnd 需要 HTTPS,而範例中的程式碼會假設您已清除該核取方塊。 一般而言,Visual Studio 所使用的 .NET 開發人員憑證僅支援外部對容器要求,而不支援容器對容器要求。

Screenshot of creating the Web API project.

  1. 將專案新增至相同的解決方案,並將其命名為 WebAPI。 選取 [API] 作為專案類型,並清除 [針對 HTTPS 進行設定] 的核取方塊。 在此設計中,我們僅將 SSL 用於與用戶端之間的通訊,而不是用於相同 Web 應用程式中的容器之間的通訊。 只有 WebFrontEnd 需要 HTTPS,而範例中的程式碼會假設您已清除該核取方塊。 一般而言,Visual Studio 所使用的 .NET 開發人員憑證僅支援外部對容器要求,而不支援容器對容器要求。

    Screenshot of creating the Web API project.

  2. 新增對 Redis 快取的支援。 新增 NuGet 套件 Microsoft.Extensions.Caching.StackExchangeRedis (非 StackExchange.Redis)。 在 Program.cs 中,在 var app = builder.Build() 正前方新增下列程式碼:

    builder.Services.AddStackExchangeRedisCache(options =>
       {
          options.Configuration = "redis:6379"; // redis is the container name of the redis service. 6379 is the default port
          options.InstanceName = "SampleInstance";
       });
    
  3. Program.cs 中新增適用於 Microsoft.Extensions.Caching.DistributedMicrosoft.Extensions.Caching.StackExchangeRedis 的 using 指示詞。

    using Microsoft.Extensions.Caching.Distributed;
    using Microsoft.Extensions.Caching.StackExchangeRedis;
    
  4. 在 Web API 專案中,刪除現有的 WeatherForecast.csControllers/WeatherForecastController.cs,然後在 [Controllers] 底下新增具有下列內容的 CounterController.cs 檔案:

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Caching.Distributed;
    using StackExchange.Redis;
    
    namespace WebApi.Controllers
    {
        [ApiController]
        [Route("[controller]")]
        public class CounterController : ControllerBase
        {
            private readonly ILogger<CounterController> _logger;
            private readonly IDistributedCache _cache;
    
            public CounterController(ILogger<CounterController> logger, IDistributedCache cache)
            {
                _logger = logger;
                _cache = cache;
            }
    
            [HttpGet(Name = "GetCounter")]
            public string Get()
            {
                string key = "Counter";
                string? result = null;
                try
                {
                    var counterStr = _cache.GetString(key);
                    if (int.TryParse(counterStr, out int counter))
                    {
                        counter++;
                    }
                    else
                    {
                        counter = 0;
                    }
                    result = counter.ToString();
                    _cache.SetString(key, result);
                }
                catch(RedisConnectionException)
                {
                    result = "Redis cache is not found.";
                }
                return result;
            }
        }
    }
    

    服務會在每次存取頁面時遞增計數器,並將計數器儲存在 Redis 快取中。

新增程式碼以呼叫 Web API

  1. WebFrontEnd 專案中,開啟 Index.cshtml.cs 檔案,並將 OnGet 方法取代為下列程式碼。

     public async Task OnGet()
     {
        ViewData["Message"] = "Hello from webfrontend";
    
        using (var client = new System.Net.Http.HttpClient())
        {
           // Call *mywebapi*, and display its response in the page
           var request = new System.Net.Http.HttpRequestMessage();
           request.RequestUri = new Uri("http://mywebapi/WeatherForecast");
           // request.RequestUri = new Uri("http://mywebapi/api/values/1"); // For ASP.NET 2.x, comment out previous line and uncomment this line.
           var response = await client.SendAsync(request);
           ViewData["Message"] += " and " + await response.Content.ReadAsStringAsync();
        }
     }
    

    注意

    在真實世界的程式碼中,您不應該在每個要求之後都處置 HttpClient。 如需最佳做法,請參閱 使用 HttpClientFactory 實作復原 HTTP 要求

  2. 在 [Index.cshtml] 檔案中,新增一行以顯示 ViewData["Message"],讓檔案看起來像下列程式碼:

    @page
    @model IndexModel
    @{
       ViewData["Title"] = "Home page";
    }
    
    <div class="text-center">
       <h1 class="display-4">Welcome</h1>
       <p>Learn about <a href="/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
       <p>@ViewData["Message"]</p>
    </div>
    
  3. (僅限 ASP.NET 2.x) 現在,在 Web API 專案中,將程式碼新增至 Values 控制器,以針對從 webfrontend 新增之呼叫,自訂由 API 傳回的訊息。

    // GET api/values/5
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
       return "webapi (with value " + id + ")";
    }
    

    注意

    在 .NET Core 3.1 和更新版本中,您可以使用提供的 WeatherForecast API,而不是這個額外的程式碼。 不過,您必須將 Web API 專案中針對 UseHttpsRedirection 的呼叫註解化,因為此程式碼會使用 HTTP (而不是 HTTPS) 來進行呼叫。

          //app.UseHttpsRedirection();
    

新增 Docker Compose 支援

  1. WebFrontEnd 專案中,選擇 [新增] > [容器協調器支援]。 [Docker 支援選項] 對話方塊隨即出現。

  2. 選擇 [Docker Compose]

  3. 選擇您的目標 OS,例如 Linux。

    Screenshot of choosing the Target OS.

    Visual Studio 會在解決方案的 docker-compose 節點中建立 docker-compose.yml 檔案與 .dockerignore 檔案,且該專案會以粗體字型顯示,表示其為起始專案。

    Screenshot of Solution Explorer with docker-compose project added.

    docker-compose.yml 會顯示如下:

    version: '3.4'
    
     services:
       webfrontend:
         image: ${DOCKER_REGISTRY-}webfrontend
         build:
           context: .
           dockerfile: WebFrontEnd/Dockerfile
    

    第一行中指定的 versionDocker Compose 檔案版本 (英文)。 您通常不應該加以變更,因為工具會加以使用來了解如何解譯檔案。

    .dockerignore 檔案包含您不希望 Docker 包含在容器中的檔案類型和副檔名。 這些檔案通常會與開發環境和原始檔控制產生關聯,而不屬於您正在開發的應用程式或服務。

    如需執行中命令的詳細資料,請查看輸出窗格的 [容器工具] 區段。 您可以看到命令列工具 docker-compose 是用來設定及建立執行階段容器。

  4. 在 Web API 專案中,再次以滑鼠右鍵按一下專案節點,然後選擇 [新增]>[容器協調器支援]。 選擇 [Docker Compose],然後選取相同的目標 OS。

    注意

    在此步驟中,Visual Studio 會詢問是否要建立 Dockerfile。 如果您針對已經有 Docker 支援的專案這麼做,系統會提示您是否要覆寫現有的 Dockerfile。 如果您已在 Dockerfile 中做出想要保留的變更,請選擇 [否]。

    Visual Studio 也會對您的 docker compose YML 檔案進行一些變更。 現在已同時包括這兩個服務。

    version: '3.4'
    
    services:
      webfrontend:
        image: ${DOCKER_REGISTRY-}webfrontend
        build:
          context: .
          dockerfile: WebFrontEnd/Dockerfile
    
      mywebapi:
        image: ${DOCKER_REGISTRY-}mywebapi
        build:
          context: .
          dockerfile: MyWebAPI/Dockerfile
    
  5. 您新增容器協調流程的第一個專案會設定為在執行或偵錯時啟動。 您可以在 docker-compose 專案的 [專案屬性] 中設定啟動動作。 在 docker-compose 專案節點上,以滑鼠右鍵按一下以開啟捷徑功能表,然後選擇 [屬性],或使用 Alt+Enter。 下列螢幕擷取畫面顯示解決方案在此應使用的屬性。 例如,您可以自訂 [服務 URL] 屬性來變更載入的頁面。

    Screenshot of docker-compose project properties.

    以下是您啟動時所會看到的內容 (.NET Core 2.x 版):

    Screenshot of running web app.

    適用於 .NET 3.1 的 Web 應用程式會以 JSON 格式顯示天氣資料。

  6. 現在假設您只想要將偵錯工具附加至 WebFrontEnd,而不是 Web API 專案。 從功能表列,您可以使用 [開始] 按鈕旁的下拉式清單來顯示偵錯選項功能表;選擇 [管理 Docker Compose 啟動設定]

    Screenshot of Debug Manage Compose Settings menu item.

    [管理 Docker Compose 啟動設定] 對話方塊隨即出現。 透過此對話方塊,您可以控制在偵錯工作階段期間啟動的服務子集 (其可以在附加或不附加偵錯工具的情況下啟動),以及啟動服務和 URL。 請參閱啟動 Compose 服務的子集 (部分機器翻譯)。

    Screenshot of Manage Docker Compose Launch Settings dialog box.

    選擇 [新增] 以建立新設定檔,並將其命名為 Debug WebFrontEnd only。 然後將 Web API 專案設定為 [啟動但不偵錯],將 WebFrontEnd 專案維持設定為 [啟動並偵錯],然後選擇 [儲存]

    已選擇新設定作為下一個 F5 的預設值。

  7. F5 以確認其如預期般運作。

恭喜您,您正在執行具有自訂 Docker Compose 設定檔的 Docker Compose 應用程式。

  1. WebFrontEnd 專案中,開啟 Index.cshtml.cs 檔案,並將 OnGet 方法取代為下列程式碼。

    public async Task OnGet()
    {
       using (var client = new System.Net.Http.HttpClient())
       {
          // Call *mywebapi*, and display its response in the page
          var request = new System.Net.Http.HttpRequestMessage();
          // webapi is the container name
          request.RequestUri = new Uri("http://webapi/Counter");
          var response = await client.SendAsync(request);
          string counter = await response.Content.ReadAsStringAsync();
          ViewData["Message"] = $"Counter value from cache :{counter}";
       }
    }
    

    注意

    在真實世界的程式碼中,您不應該在每個要求之後都處置 HttpClient。 如需最佳做法,請參閱 使用 HttpClientFactory 實作復原 HTTP 要求

  2. 在 [Index.cshtml] 檔案中,新增一行以顯示 ViewData["Message"],讓檔案看起來像下列程式碼:

    @page
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }
    
    <div class="text-center">
        <h1 class="display-4">Welcome</h1>
        <p>Learn about <a href="/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
        <p>@ViewData["Message"]</p>
    </div>
    

    此程式碼會顯示從 Web API 專案傳回之計數器的值。

新增 Docker Compose 支援

  1. WebFrontEnd 專案中,選擇 [新增] > [容器協調器支援]。 [Docker 支援選項] 對話方塊隨即出現。

  2. 選擇 [Docker Compose]

  3. 選擇您的目標 OS,例如 Linux。

    Screenshot of choosing the Target OS.

    Visual Studio 會在解決方案的 docker-compose 節點中建立 docker-compose.yml 檔案與 .dockerignore 檔案,且該專案會以粗體字型顯示,表示其為起始專案。

    Screenshot of Solution Explorer with docker-compose project added.

    docker-compose.yml 會顯示如下:

    version: '3.4'
    
     services:
       webfrontend:
         image: ${DOCKER_REGISTRY-}webfrontend
         build:
           context: .
           dockerfile: WebFrontEnd/Dockerfile
    

    第一行中指定的 versionDocker Compose 檔案版本 (英文)。 您通常不應該加以變更,因為工具會加以使用來了解如何解譯檔案。

    .dockerignore 檔案包含您不希望 Docker 包含在容器中的檔案類型和副檔名。 這些檔案通常會與開發環境和原始檔控制產生關聯,而不屬於您正在開發的應用程式或服務。

    如需執行中命令的詳細資料,請查看輸出窗格的 [容器工具] 區段。 您可以看到命令列工具 docker-compose 是用來設定及建立執行階段容器。

  4. 在 Web API 專案中,再次以滑鼠右鍵按一下專案節點,然後選擇 [新增]>[容器協調器支援]。 選擇 [Docker Compose],然後選取相同的目標 OS。

    注意

    在此步驟中,Visual Studio 會詢問是否要建立 Dockerfile。 如果您針對已經有 Docker 支援的專案這麼做,系統會提示您是否要覆寫現有的 Dockerfile。 如果您已在 Dockerfile 中做出想要保留的變更,請選擇 [否]。

    Visual Studio 也會對您的 docker compose YML 檔案進行一些變更。 現在已同時包括這兩個服務。

    version: '3.4'
    
    services:
      webfrontend:
        image: ${DOCKER_REGISTRY-}webfrontend
        build:
          context: .
          dockerfile: WebFrontEnd/Dockerfile
    
      mywebapi:
        image: ${DOCKER_REGISTRY-}mywebapi
        build:
          context: .
          dockerfile: MyWebAPI/Dockerfile
    
  5. 將 Redis 快取新增至 docker.compose.yml 檔案:

    redis:
       image: redis
    

    請確定縮排與其他兩個服務位於相同的層級。

  6. 您新增容器協調流程的第一個專案會設定為在執行或偵錯時啟動。 您可以在 docker-compose 專案的 [專案屬性] 中設定啟動動作。 在 docker-compose 專案節點上,以滑鼠右鍵按一下以開啟捷徑功能表,然後選擇 [屬性],或使用 Alt+Enter。 例如,您可以自訂 [服務 URL] 屬性來變更載入的頁面。

    Screenshot of docker-compose project properties.

  7. 請按 F5。 以下是您啟動時所會看到的內容:

    Screenshot of running web app.

  8. 您可以使用 [容器] 視窗來監視容器。 如果您沒有看到視窗,請使用搜尋方塊、按 Ctrl+KCtrl+O,或按 Ctrl+Q。 在 [功能搜尋] 底下,搜尋 containers,然後從清單中選擇 [檢視>其他 Windows> 容器]。

  9. 展開 [解決方案容器] 節點,然後選擇 Docker Compose 專案的節點,以在此視窗的 [記錄] 索引標籤中檢視合併的記錄。

    Screenshot showing viewing the Logs tab in the Containers window.

    您也可以選取個別容器的節點,以檢視記錄、環境變數、檔案系統和其他詳細資料。

設定啟動設定檔

  1. 此解決方案具有 Redis 快取,但每次啟動偵錯工作階段時都重建 Redis 快取容器沒有效率。 若要避免這種情況,您可以設定幾個啟動設定檔。 建立一個設定檔以啟動 Redis 快取。 建立第二個設定檔以啟動其他服務。 第二個設定檔可以使用已在執行的 Redis 快取容器。 您可以從功能表列使用 [開始] 按鈕旁的下拉式清單,來開啟具有偵錯選項的功能表。 選取 [管理 Docker Compose 啟動設定]

    Screenshot of Debug Manage Compose Settings menu item.

    [管理 Docker Compose 啟動設定] 對話方塊隨即出現。 透過此對話方塊,您可以控制在偵錯工作階段期間啟動的服務子集 (其可以在附加或不附加偵錯工具的情況下啟動),以及啟動服務和 URL。 請參閱啟動 Compose 服務的子集 (部分機器翻譯)。

    Screenshot of Manage Docker Compose Launch Settings dialog box.

    選擇 [新增] 以建立新設定檔,並將其命名為 Start Redis。 然後將 Redis 容器設定為 [啟動但不偵錯],將另一個維持設定為 [不要啟動],然後選擇 [儲存]

    Screenshot showing creating the Redis profile that starts the Redis service only.

    然後,建立另一個不會啟動 Redis,但會啟動其他兩個服務的設定檔 Start My Services

    Screenshot showing creating the Services profile that starts the other services.

    (選擇性) 建立第三個設定檔 Start All 以啟動所有服務。 您可以針對 Redis 選擇 [啟動但不偵錯]

  2. 從主 Visual Studio 工具列的下拉式清單中選擇 [啟動 Redis],按 F5。 Redis 容器會建置並啟動。 您可以使用 [容器] 視窗來查看其正在執行中。 接下來,從下拉式清單中選擇 [啟動我的服務],然後按 F5 來加以啟動。 現在您可以在許多後續的偵錯工作階段中讓 Redis 快取容器保持執行。 每次使用 [啟動我的服務] 時,那些服務都會使用相同的 Redis 快取容器。

恭喜您,您正在執行具有自訂 Docker Compose 設定檔的 Docker Compose 應用程式。

下一步

查看將容器部署至 Azure (部分機器翻譯) 的選項。

另請參閱

Docker Compose (英文)
容器工具 (部分機器翻譯)