用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个容器来构建应用程序。配置图如下所示:
通常情况下,当在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来确认操作是否正常。
总结
我們介紹了使用 docker-compose 構建 Docker 應用程式的示例。
由於 .NET Core 具有跨平台的特點,因此我們希望使用 Docker 進行開發能夠更加繁榮。
如果在ASP.NET Core和Azure上进行开发,您可以通过使用优秀的PaaS(如Web Apps和SQL Database)来轻松构建可扩展的应用程序。因此,使用像Docker这样的容器技术的场景可能并不多。
然而,通过将ASP.NET Core应用程序容器化,可以将其移植到AWS或GCP等其他云服务,或者享受到容器编排(如Kubernetes)的好处。作为系统架构的选择之一,考虑这个价值是非常合理的。