使用 Docker Compose 的多容器 ASP.NET Core 应用程序

作者 : 慕源网 本文共11265个字,预计阅读时间需要29分钟 发布时间: 2022-01-25 共192人阅读

在本教程中,我将使用 Docker Compose 创建一个多容器 ASP.NET Core 应用程序。在这里,容器将相互通信。APP中将有2个项目:

  • 1. ASP.NET Core Web API 项目将提供一个随机joke。
  • 2. ASP.NET Core Razor 项目将调用 Web API 项目并从中获取随机joke。收到joke后,它将显示在 HTML 表格中。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

什么是 Docker Compose

Docker Compose是一个运行多容器 Docker 应用程序的工具。它与 Docker 引擎捆绑在一起,并在您安装 docker 桌面时自动安装。您使用 YAML 文件来处理 docker compose。在 YAML 文件中,您可以定义不同的容器、镜像以及在这些镜像上运行的应用程序。您还需要定义 dockerfiles 和其他必要的设置。

一个示例 YAML 文件定义如下:

version: '3.4'

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

  mywebapi:
    image: ${DOCKER_REGISTRY-}mywebapi
    build:
      context: .
      dockerfile: MyWebAPI/Dockerfile

当我们将使用 docker compose 创建应用程序并在多个容器上运行时,您将了解更多关于 docker compose 的信息。

创建多项目 ASP.NET Core 应用程序

在 Visual Studio 中创建一个新的 Web 应用程序。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

将您的应用程序命名为MultiApp,然后取消选中选项Place solution and project in the same directory

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

不要选择启用 Docker 支持。稍后我们将添加 Docker 支持。

接下来,选择名为ASP.NET Core Web App的模板,用于创建基于 ASP.NET Core Razor Pages 的基本应用程序。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

创建一个 Web API 项目

将新项目添加到同一解决方案中。为此,请右键单击解决方案资源管理器中的解决方案名称,然后选择Add >> New Project

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

选择ASP.NET Core Web 应用程序

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

命名为MultiApi

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

选择模板作为ASP.NET Core Web API。确保取消选中“为 HTTPS 配置”复选框。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

这样做是因为 Docker 容器之间的通信不需要 SSL,只有主机和容器之间的通信需要 SSL。那是当我们在浏览器中输入应用程序的 URL 来打开应用程序时。

创建 API 控制器

在“MultiApi”项目中,使用以下代码在Models文件夹中创建一个名为Joke.cs的新类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MultiApi.Models
{
    public class Joke
    {
        public string Name { get; set; }
        public string Text { get; set; }
        public string Category { get; set; }
    }
}

此类用于在调用时将随机发送给客户端的joke。

接下来在Controllers文件夹中添加一个名为JokeController.cs的新控制器,代码如下:

using Microsoft.AspNetCore.Mvc;
using MultiApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MultiApi.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class JokeController : ControllerBase
    {
        [HttpGet]
        public Joke Get()
        {
            Random rand = new Random();
            int toSkip = rand.Next(0, 10);
            Joke joke = Repository().Skip(toSkip).Take(1).FirstOrDefault();
            return joke;
        }


        public List<Joke> Repository()
        {
            List<Joke> jokeList = new List<Joke> {
                new Joke {Name = "RATTLE SNAKE", Text = "Two men are hiking through the woods when one of them cries out, “Snake! Run!” His companion laughs at him. “Oh, relax. It’s only a baby,” he says. “Don’t you!", Category="Animal" },
                new Joke {Name = "HORSE RIDER", Text = "To be or not to be a horse rider, that is equestrian. —Mark Simmons, comedian", Category="Animal" },
                new Joke {Name = "POSTURE CAT", Text = "What did the grandma cat say to her grandson when she saw him slouching? A: You need to pay more attention to my pawsture.", Category="Animal" },
                new Joke {Name = "HE CAN DO IT HIMSELF", Text = "It was my first night caring for an elderly patient. When he grew sleepy, I wheeled his chair as close to the bed as possible and, using the techniques I’d...", Category="Dockor" },
                new Joke {Name = "ON THE BADGE", Text = "My 85-year-old grandfather was rushed to the hospital with a possible concussion. The doctor asked him a series of questions: “Do you know where you are?” “I’m at Rex Hospital.”...", Category="Dockor" },
                new Joke {Name = "THE NURSE HAS MY TEETH", Text = "As a brain wave technologist, I often ask postoperative patients to smile to make sure their facial nerves are intact. It always struck me as odd to be asking this...", Category="Dockor" },
                new Joke {Name = "GLUTEN ATTACK", Text = "Guy staring at an ambulance in front of Whole Foods: “Somebody must have accidentally eaten gluten.”", Category="Food" },
                new Joke {Name = "MORNING TEA", Text = "What has T in the beginning, T in the middle, and T at the end? A: A teapot.", Category="Food" },
                new Joke {Name = "MAKE ME A SANDWICH", Text = "My husband and I were daydreaming about what we would do if we won the lottery. I started: “I’d hire a cook so that I could just say, ‘Hey, make...", Category="Marriage" },
                new Joke {Name = "SELL IT", Text = "As my wife and I prepared for our garage sale, I came across a painting. Looking at the back, I discovered that I had written “To my beautiful wife on...", Category="Marriage" }
                };

            return jokeList;
        }
    }
}

请注意控制器上的 2 个属性,这将使其成为 API 控制器,因此它将以 json 格式将joke发送给客户端。这些属性是:

[ApiController]
[Route("api/[controller]")]

另请注意,此控制器是从ControllerBase继承的。

Web API 控制器有一个 HTTP GET 方法,该方法将返回一个随机joke。

[HttpGet]
public Joke Get()
{
    Random rand = new Random();
    int toSkip = rand.Next(0, 10);
    Joke joke = Repository().Skip(toSkip).Take(1).FirstOrDefault();
    return joke;
}
Repository 方法包含 10 个笑话。

public List<Joke> Repository()
{
…
}
从“MultiApp”项目调用 Web API

现在打开保存在MultiApp项目的“Pages”文件夹中的Index.cshtml.cs页面,并将OnGet()方法代码更改为:

public async Task OnGet()
{
    using (var client = new System.Net.Http.HttpClient())
    {
        var request = new System.Net.Http.HttpRequestMessage();
        request.RequestUri = new Uri("http://localhost:53205/api/Joke");
        var response = await client.SendAsync(request);
        var joke = await response.Content.ReadAsStringAsync();

        var details = JObject.Parse(joke);
        ViewData["Joke"] = details["name"] + ";;" + details["text"] + ";;" + details["category"];
    }
} 

在这种方法中,我调用了MultiApi项目中保存的 Web API。注意 web api 的 url – http://localhost:53205/api/Joke您可以通过选择MultiApi项目的属性来获取此 url ,见下图。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

JObject 是Newtonsoft.Json.Linq类的对象,用于将包含 json 的字符串转换为 JObject 类型。之后,您可以将 json 的各个值提取为:

details["name"]
details["text"]
details["category"]
收到joke后,会将其保存到索引视图的 ViewData 变量中。因此,在索引视图中,我将在 HTML 表中显示笑话。因此,编辑保存在Pages文件夹中的Index.cshtml以包含一个 HTML 表,其代码以突出显示的方式显示:
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
    <table class="table table-sm table-striped table-bordered m-2">
        <thead>
            <tr>
                <th>Name</th>
                <th>Text</th>
                <th>Category</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>@ViewData["Joke"].ToString().Split(";;")[0]</td>
                <td>@ViewData["Joke"].ToString().Split(";;")[1]</td>
                <td>@ViewData["Joke"].ToString().Split(";;")[2]</td>
            </tr>
        </tbody>
    </table>
</div>
多个启动项目

在解决方案资源管理器中右键单击解决方案名称并选择属性。这里选择Multiple Startup Project。确保为这两个项目选择“开始”,如下图所示。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

现在在 Visual Studio 中运行该应用程序,您将在页面上看到一个joke。检查下图,我展示了这个东西。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

从 Docker Compose 创建多容器

多项目 ASP.NET Core 应用程序已准备就绪,是时候使用Docker Compose为其创建多容器了。

docker-compose.yml文件的目的是指定docker引擎在 2 个容器中运行这个应用程序。

  • 1.运行MultiApp项目的容器。
  • 2.运行MultiApi项目的容器。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

右键单击解决方案资源管理器上的MultiApp项目名称,然后选择Add >> Container Orchestrator Support

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

将出现“添加 Container Orchestrator 支持”对话框。选择Docker Compose并单击 OK 按钮。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

将打开一个新窗口,您需要在其中选择目标操作系统。在这里选择“Linux”并单击“确定”按钮。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

一旦你点击 OK 按钮,Visual Studio 就会做两件事:

1、创建docker-compose项目、yaml文件和.dockerignore文件

在名为 docker -compose的新项目中创建一个docker-compose.yml文件和一个.dockerignore文件。此项目已添加到解决方案中。下图显示了这一点:

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

docker-compose 项目以粗体显示,因为它也是作为启动项目。

还要检查顶部的 Visual Studio 菜单栏,您可以在其中看到这个新创建的项目被设置为解决方案的启动项目。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

.dockerignore 文件告诉 docker 服务器不应包含在容器中的文件类型和扩展名。

打开docker-compose.yml,它将有以下代码:

version: '3.4'

services:
  multiapp:
    image: ${DOCKER_REGISTRY-}multiapp
    build:
      context: .
      dockerfile: MultiApp/Dockerfile

让我们了解这个 yaml 文件在说什么。

从顶部开始,它定义了一个版本号,即 3.4 – version: ‘3.4’

然后是代表将在应用程序中创建的容器的服务。它指定了一个名为multiapp的容器。

services:
  multiapp:

然后指定镜像名称。基本上,此镜像将包含MultiApp项目。

image: ${DOCKER_REGISTRY-}multiapp

接下来,有一个“build”部分,它指定了构建镜像的过程。在这里,我们定义了包含 Dockerfile 的目录的路径。它被解释为相对于 Compose 文件的位置。

build:
  context: .
  dockerfile: MultiApp/Dockerfile
2.为“MultiApp”项目创建一个Dockerfile

Visual Studio 还在MultiApp项目中为该项目创建一个 Dockerfile。它的代码如下:

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
 
FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
 
FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build
WORKDIR /src
COPY ["MultiApp/MultiApp.csproj", "MultiApp/"]
RUN dotnet restore "MultiApp/MultiApp.csproj"
COPY . .
WORKDIR "/src/MultiApp"
RUN dotnet build "MultiApp.csproj" -c Release -o /app/build
 
FROM build AS publish
RUN dotnet publish "MultiApp.csproj" -c Release -o /app/publish
 
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MultiApp.dll"]

Dockerfile 以层或步骤创建镜像。我已经在我之前的教程中详细解释了它,所以请检查一下——什么是 Dockerfile

接下来,您必须为第二个项目MultiApi添加Container Orchestrator 支持

右键单击解决方案资源管理器上的MultiApi项目名称,然后选择Add >> Container Orchestrator Support

使用 Docker Compose 的多容器 ASP.NET Core 应用程序
出现Add Container Orchestrator Support对话框,在此处选择Docker Compose并单击 OK 按钮。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

接下来,将打开一个新窗口,您需要在其中选择 Target OS。因此,选择“Linux”并单击“确定”按钮。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

一旦你点击 OK 按钮,Visual Studio 就会做两件事:

  • 1. 为MultiApi项目创建一个新的Dockerfile 。
  • 2. 向docker-compose.yml文件添加新服务。此服务指定将运行第二个项目的第二个容器,即MultiApi

打开docker-compose.yml,您可以注意到添加到其中的第二个服务。

version: '3.4'
 
services:
  multiapp:
    image: ${DOCKER_REGISTRY-}multiapp
    build:
      context: .
      dockerfile: MultiApp/Dockerfile
 
  multiapi:
    image: ${DOCKER_REGISTRY-}multiapi
    build:
      context: .
      dockerfile: MultiApi/Dockerfile

恭喜,我们完成了告诉 docker 如何使用docker-compose.yml为我们的 ASP.NET Core 应用程序构建多容器的任务。现在是构建镜像并运行 compose 的时候了。

Docker Compose 构建并运行应用程序

在 docker 中运行 APP 之前,您必须更改 Web API 的 url。因此,打开位于MultiApp项目的Pages文件夹中的index.cshtml.cs文件。这里将 URL 从http://localhost:53205/api/Joke更改为http://multiapi/api/Joke。请参阅下面给出的突出显示的代码:

public async Task OnGet()
{
    using (var client = new System.Net.Http.HttpClient())
    {
        var request = new System.Net.Http.HttpRequestMessage();
        request.RequestUri = new Uri("http://multiapi/api/Joke");
        var response = await client.SendAsync(request);
        var joke = await response.Content.ReadAsStringAsync();
 
        var details = JObject.Parse(joke);
        ViewData["Joke"] = details["name"] + ";;" + details["text"] + ";;" + details["category"];
    }
}

这样做是因为现在应用程序将在 2 个容器中运行,因此您现在可以使用服务名称 (multiapi) 来调用 Web API。

您可以在 Visual Studio 中运行该项目,它将从 2 个 docker 容器中运行它。我制作了一个小视频,展示了这个应用程序在 vs 中的运行情况。

现在检查 docker 桌面,它将显示为此应用程序运行的多容器。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

为 HTTPS 公开端口和配置环境变量

我现在将容器的端口公开给主机。这将有助于直接使用浏览器上的 url 调用容器(不使用 Visual Studio)。

因此,在docker-compose.yml文件中添加端口和环境部分。

version: '3.4'
 
services:
  multiapp:
    image: ${DOCKER_REGISTRY-}multiapp
    build:
      context: .
      dockerfile: MultiApp/Dockerfile
    ports:
      - "9000:443"
      - "9001:80"
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=https://+:443;http://+:80
      - ASPNETCORE_HTTPS_PORT=9000
      - ASPNETCORE_Kestrel__Certificates__Default__Password=mypass123
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
    volumes:
        - ./MultiApp/https/aspnetapp.pfx:/https/aspnetapp.pfx:ro
 
  multiapi:
    image: ${DOCKER_REGISTRY-}multiapi
    build:
      context: .
      dockerfile: MultiApi/Dockerfile

通过这些设置,我指定了 2 个将被公开的端口。端口以“主机端口:容器端口”的形式公开。因此,我为 https 公开了端口 9000,为 http 公开了 9001。

ports: 
  - "9000:443"
  - "9001:80"

然后我指定了5个环境变量来指定环境、urls、https端口、ssl证书密码和ssl路径。

environment:
  - ASPNETCORE_ENVIRONMENT=Development
  - ASPNETCORE_URLS=https://+:443;http://+:80
  - ASPNETCORE_HTTPS_PORT=9000
  - ASPNETCORE_Kestrel__Certificates__Default__Password=mypass123
  - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx

请注意,端口 9000 是为运行我们应用程序的容器的 https 类型 url 指定的。我将 ssl 证书密码指定为“mypass123”。稍后我将使用此密码生成此证书。

另请注意,使用环境变量ASPNETCORE_Kestrel__Certificates__Default__Path我指定了容器中将挂载 ssl 证书的路径。这个路径是“/https/aspnetapp.pfx”。

下一节是关于卷的,我在其中指定了证书将如何挂载到容器中。

volumes:
    - ./MultiApp/https/aspnetapp.pfx:/https/aspnetapp.pfx:ro

在这里,我是说驱动器上的证书位置将从其装载到容器的位置是“MultiApp/https/aspnetapp.pfx”。这 ”。” 开头告诉路径从 docker-compose.yml 文件的目录开始。所以“MultiApp”目录与 docker-compose.yml 文件所在的目录相同。

第二个路径定义了这个 ssl 证书将被挂载到的容器上的路径。这个路径是“/https/aspnetapp.pfx”。

为开发生成 SSL 证书

我必须使用dotnet dev-certs为开发生成一个新的 SSL证书。因此,在您的命令提示符下运行以下命令:

dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\aspnetapp.pfx -p mypass123

这将创建一个名为aspnetapp.pfx的开发证书,密码为 mypass123

SSL 证书的路径将位于用户配置文件文件夹中,因为我已从 %USERPROFILE%\ 引用它。在我的例子中,SSL 的完整路径是:

C:\Users\Avita\.aspnet\https

这里 Avita 是我的 windows 登录名,将其更改为您的登录名,您将在您的电脑中找到它。在下图中,我展示了刚刚在我的电脑上生成的 SSL 证书文件。

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

因此,复制此证书并将其粘贴到MultiApp项目文件夹中的https文件夹中。检查下面我标记的镜像:

使用 Docker Compose 的多容器 ASP.NET Core 应用程序

下一个要运行的命令是信任 ASP.NET Core HTTPS 开发证书。该命令在下面给出。

dotnet dev-certs https –trust

如果您在运行上述命令后收到提示,请确保您接受它。

在 Docker Compose 上运行应用程序

Docker compose 有 2 个主要命令用于构建服务和运行容器。在您的命令提示符中,转到docker-compose.yml文件的目录并运行构建命令:

docker-compose build

这将构建服务并为我们的应用创建 2 个镜像。

接下来,为这 2 个镜像创建并启动 2 个容器。该命令在下面给出。

docker-compose up

现在您可以简单地打开 url – https://localhost:9000/来打开多容器应用程序。我在下面的视频中展示了这一点。

您现在可以下载本教程的源代码:

下载

结论

在本教程中,我使用docker compose创建了一个多容器 ASP.NET Core 应用程序。这些容器也相互通信。后来,我添加了 ssl 证书并将应用程序暴露在 https 端口上。请在 facebook、twitter 和其他网站上分享本教程,以便其他开发人员也可以使用它来构建 docker 多容器应用程序。

 


慕源网 » 使用 Docker Compose 的多容器 ASP.NET Core 应用程序

常见问题FAQ

程序仅供学习研究,请勿用于非法用途,不得违反国家法律,否则后果自负,一切法律责任与本站无关。
请仔细阅读以上条款再购买,拍下即代表同意条款并遵守约定,谢谢大家支持理解!

发表评论

开通VIP 享更多特权,建议使用QQ登录