用docker-compose构建ASP.NET Core的Web应用程序作为Docker应用程序

简述

我将介绍一个以ASP.NET Core示例Web应用程序为主题的例子,演示如何使用docker-compose构建Docker应用程序的运行环境。

更新记录

    2023/07/01:各種、ソフトウェア・ミドルウェアのバージョンを更新しました。

环境

    • Windows11

 

    • Visual Studio 2022

 

    • ASP.NET Core (.NET6)

 

    Docker for Windows

样本应用程序

这是一个以题材为基础的示例应用程序。
https://github.com/tYoshiyuki/dotnet-core-web-sample

这是一个简单的ToDo Web应用程序。事务数据被保存在数据库(SQL Server)中。现在让我们尝试使用Docker进行容器化。

系统配置 (xì

这次我们将使用Docker for Windows在本地PC上搭建Docker环境。在本地开发时,我们使用了IIS Express和LocalDB,但现在我们要进行更改。前端使用Nginx,数据库使用SQL Express的Docker镜像,共包括3个容器来构建应用程序。配置图如下所示:

image.png

通常情况下,当在IIS上托管ASP.NET Core应用程序时,通过ASP.NET Core的中间件使应用程序与IIS进行集成运行。如果将Nginx配置为反向代理作为前端之后,可以使用Kestrel运行ASP.NET Core应用程序,并将HTTP通信转发到Kestrel。

Dockerfile-创作Docker文件

1. ASP.NET Core 应用程序

首先,为了将ASP.NET Core应用程序容器化,我们需要创建一个Dockerfile。您可以在Visual Studio > 项目 > 右键单击”添加Docker支持” > 选择目标操作系统为Linux的Dockerfile进行编辑。

FROM mcr.microsoft.com/dotnet/aspnet:6.0.1-bullseye-slim AS base

WORKDIR /app
# EXPOSE 80
# EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0.101-bullseye-slim AS build
WORKDIR /src
COPY ["DotNetCoreWebSample.Web.csproj", "./"]
RUN dotnet restore "DotNetCoreWebSample.Web.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "DotNetCoreWebSample.Web.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "DotNetCoreWebSample.Web.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV ASPNETCORE_URLS http://*:5000
ENTRYPOINT ["dotnet", "DotNetCoreWebSample.Web.dll"]

这里省略了有关Dockerfile的解释,但默认情况下进行了多阶段构建以减小Docker镜像的大小。关键是 [ENV ASPNETCORE_URLS http://*:5000],指定了Kestrel监听的端口号。稍后在通过Nginx转发请求时,将成为目标端口号。

另外,按照官方文档的指示,我也会对源代码进行少许更改。
https://docs.microsoft.com/ja-jp/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-3.1

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            // ・・・一部省略・・・

            app.UseForwardedHeaders(new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
            });

            // ・・・一部省略・・・

在通过反向代理时,使 X-Forwarded-For 和 X-Forwarded-Proto 头部进行传递。如果在 IIS 上运行 ASP.NET Core 应用程序,则默认情况下是启用的,需要注意。

建议您阅读公式文档,因为其中已经包含了相关信息。
https://docs.microsoft.com/ja-jp/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-3.1

2. Nginx (Chinese: 引擎实现)

接下来,我们将为Nginx创建配置。

FROM nginx:latest

COPY ./nginx.conf /etc/nginx/nginx.conf

COPY ./site.conf.template /etc/nginx/templates/site.conf.template

CMD [ "nginx", "-g", "daemon off;" ]
worker_processes 1;

events { worker_connections 1024; }

http {
    sendfile on;

    include /etc/nginx/conf.d/site.conf;
}
upstream web-app {
    server ${BACKEND_HOST};
}

server {
    listen 80;
    server_name $hostname;
    location / {
        proxy_pass         http://web-app;
        proxy_redirect     off;
        proxy_http_version 1.1;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_set_header   X-Forwarded-Host $server_name;
    }
}

通过使用模板,我们现在可以从Nginx 1.19的Docker映像中注入环境变量。使用这个功能,我们可以将应用服务器的目标地址(BACKEND_HOST)外部注入,关于这一点,我们将在稍后的docker-compose.yml中进行说明。

3. SQL Server Express

3. SQL Server Express 是一个软件。

最后是SQL Server Express。虽然作为示例应用程序的功能来说,只用LocalDB就足够了,但是由于官方没有提供Docker镜像,所以我们将使用SQL Server Express。需要注意的是,实际上需要进行数据库数据持久化的设置,但本次将省略此步骤。

FROM mcr.microsoft.com/mssql/server:2017-latest-ubuntu

docker-compose.yml的含义是什么?

我们可以使用docker-compose来启动已创建的每个容器。


version: '3.4'

services:
  app:
    build:
      context: ./DotNetCoreWebSample.Web
      dockerfile: Dockerfile
    environment:
      ConnectionStrings__DefaultConnection: "Server=sqlexpress;Database=master;User ID=sa;Password=P@ssw0rd;initial catalog=dotnetcorewebsample;MultipleActiveResultSets=True;App=EntityFramework;"
    expose:
      - 5000
    depends_on:
      - sqlexpress

  sqlexpress:
    build:
      context: ./docker/sqlexpress
      dockerfile: Dockerfile
    environment:
      MSSQL_PID: "Express"
      ACCEPT_EULA: "Y"
      SA_PASSWORD: "P@ssw0rd"
    ports:
      - 1433:1433

  web:
    build:
      context: ./docker/nginx
    environment:
      BACKEND_HOST: "app:5000"  
    ports: 
      - 80:80

尽管描述很长,但我将解释一些要点。

首先,”ConnectionStrings__DefaultConnection: “Server=sqlexpress;Database=master;User ID=sa;Password=P@ssw0rd;initial catalog=dotnetcorewebsample;MultipleActiveResultSets=True;App=EntityFramework;”这部分设置了与SQL Server Express的连接信息。在容器启动时,将覆盖appsettings.json中设置的内容。如果要表示嵌套的JSON元素(ConnectionStrings > DefaultConnection),请使用两个下划线(__)。

在 “BACKEND_HOST: “app:5000” 的部分中,设置了将信息发送到 ASP.NET Core 应用程序的地址。在 docker-compose 中,可以通过服务名称来解析每个容器的目的地,因此配置如上所示。

运行docker-compose命令,启动每个容器。

docker-compose up -d

在执行后,您可以通过访问http://localhost来确认操作是否正常。

image.png

总结

我們介紹了使用 docker-compose 構建 Docker 應用程式的示例。
由於 .NET Core 具有跨平台的特點,因此我們希望使用 Docker 進行開發能夠更加繁榮。

如果在ASP.NET Core和Azure上进行开发,您可以通过使用优秀的PaaS(如Web Apps和SQL Database)来轻松构建可扩展的应用程序。因此,使用像Docker这样的容器技术的场景可能并不多。

然而,通过将ASP.NET Core应用程序容器化,可以将其移植到AWS或GCP等其他云服务,或者享受到容器编排(如Kubernetes)的好处。作为系统架构的选择之一,考虑这个价值是非常合理的。

广告
将在 10 秒后关闭
bannerAds