目录
在本项目中,我将向您展示如何将现有的ASP.NET Core UI、API和SQL Server部署到Docker容器,以及有关故障排除非常耗时的常见陷阱的信息。您可以在此处查看源文章和此项目的最新更新。
在这篇文章中,我们将介绍:
- 使用Docker数据卷设置SQL Server容器以实现数据持久性,并使用SQL Server Management Studio连接到SQL Server容器
- 设置Docker网络,以便SQL Server、API和UI容器可以相互通信
- 为Linux .NET环境设置自签名证书,以便UI容器信任API容器而不会出错
- 设置API和UI容器,以便可以从浏览器测试应用程序
您可以在GitHub存储库中下载此项目的代码。
项目设置
此项目的起点是使用分页和排序项目创建的,该项目具有连接到SQL Server数据库的ASP.NET前端和API。您可以下载它并确保它首先在您的计算机上运行。
要在Windows机器上运行Docker,首先需要安装WSL(Linux的Windows子系统),它依赖于Hyper-V。转到Windows中的“打开或关闭Windows功能”功能并启用Hyper-V平台,如下所示:
完成后,您可以安装 WSL(Windows Subsystem for Linux)Linux内核更新包。可以在Powershell中设置WSL的默认版本:
wsl --set-default-version 2
下载Docker桌面。在继续之前,Docker桌面应已启动并运行,如下所示:
设置SQL Server容器
我们首先需要设置一个Docker网络,这是必要的,以便SQL Server,API和UI容器可以放置在同一个网络中,以便它们可以找到彼此。
创建在命令提示符下命名为network-name的网络:
docker network create network-name
然后在命令提示符下运行以下docker pull命令以获取 SQL Server 镜像:
docker pull mcr.microsoft.com/mssql/server:2022-latest
然后,您可以使用以下docker run命令创建SQL Server容器,方法是提供:
- sql-server-password——SA(系统管理员)密码长度必须至少为10个字符,并且包含以下四组中的三组字符:大写字母、小写字母、进制数字和符号。如果密码不合格,它将不起作用。
- sql-server-volume-name——用于数据持久性的Docker数据卷的名称
- sql-server-container-name——容器的名称
- network-name——运行SQL Server容器的Docker网络的名称。
- sql-server-name——SQL Server的名称,以便API容器可以找到它
- 将容器中的 /https 位置映射到计算机位置%USERPROFILE%\.aspnet\https,映射到我的驱动器位置C:\Users\Kendall\.aspnet\https。原因是我们将使用SQL Server容器在Linux中创建要在API容器中使用的自签名证书。稍后会详细介绍这一点。
docker run -e "ACCEPT_EULA=Y" ^
-e "MSSQL_SA_PASSWORD=sql-server-password" ^
-p 1433:1433 ^
-v sql-server-volume-name:/var/opt/mssql ^
-v %USERPROFILE%\.aspnet\https:/https/ ^
--name sql-server-container-name ^
--network network-name ^
--network-alias sql-server-name ^
-d mcr.microsoft.com/mssql/server:2022-latest
运行该命令后,您应该会在Docker桌面中看到Docker数据卷:
现在,您可以通过提供SA(系统管理员)密码,在端口127上使用服务器名称为0.0.1.1433的SQL Server Management Studio连接到SQL Server、容器:
建立连接后,在应用设置中更改连接字符串。 API项目中指向容器数据库的Development.json文件:
"StarterConn": "Data Source=127.0.0.1;Initial Catalog=Starter;
User Id=sa;Password=sql-server-password"
在命令提示符下,导航到项目的 Data 文件夹并运行以下dotnet ef命令,该命令将在容器中设置数据库的结构:
dotnet ef database update -s ..\Api\Api.csproj
您可以运行位于“Data”文件夹中的文件 insertCustomer.sql 来填充一些示例数据:
设置API容器
API容器的设置需要:
- 创建与API容器具有相同域名的自签名证书。如果使用dotnet dev-certs命令生成证书,则在UI调用证书时将生成RemoteCertificateNameMismatch错误,因为域名不同。相反,您需要在Linux中使用openssl命令来生成我将向您展示的证书。
- 创建包含API代码的Docker镜像。您可以将API项目发布到目录,然后通过将已发布的API项目复制到镜像中来构建Docker镜像。
若要为API创建自签名证书,请转到Docker Desktop中的SQL Server容器并导航到/https位置,该位置映射到计算机的C:\Users\[UserName]\.aspnet\https位置,然后运行以下openssl命令以生成证书:
openssl req \
-newkey rsa:4096 -nodes -sha256 -keyout api-server.key \
-addext "subjectAltName = DNS:api-server-name" \
-x509 -days 365 -out api-server.crt
它会询问您一系列问题,您可以对所有问题采取默认值,但在询问公用名(CN)时必须指定API的服务器名称。在这种情况下,我只用api-server-name作为我的API服务器的名称。现在,您应该拥有 .crt 证书文件和.key私钥文件。然后,可以发出下面的另一个openssl命令来生成运行ASP.NET容器所需的.NET兼容.pfx 证书文件:
openssl pkcs12 -export -out api-server.pfx -inkey api-server.key -in api-server.crt
它会询问您将用于 .pfx 证书的密码,只需创建一个密码并记住它。
现在,您应该在C:\Users\[UserName]\.aspnet\https中显示以下文件,如下所示:
请注意:
- 需要将.crt和.key文件作为受信任证书安装到UI容器中
- 需要.pfx及其密码才能运行API容器
现在,让我们为API创建一个镜像。首先复制应用设置。Development.json 配置文件并将其命名为 appsettings.Container.json,它将是容器的配置文件:
在应用程序appsettings.Container.json 文件中,使用SQL Server的名称和SA(系统管理员)密码更新SQL Server连接字符串:
"StarterConn": "Data Source=sql-server-name;
Initial Catalog=Starter;User Id=sa;Password=sql-server-password"
将API项目发布到 bin 目录,然后选择如下所示的linux-x64目标运行时:
下一步是生成将包含API的Docker镜像。这是通过创建包含构建新镜像的说明的 Dockerfile 来完成的。
在API项目中,创建一个名为 Dockerfile 的文本文件(该文件必须这样命名,docker命令才能找到它),并将下面的构建说明粘贴到其中:
FROM mcr.microsoft.com/dotnet/aspnet:6.0
COPY bin/Release/net6.0/publish App/
WORKDIR /App
ENTRYPOINT ["dotnet", "Api.dll"]
Dockerfile 指定将按照以下步骤创建新镜像:
- 它使用Docker存储库中的aspnet镜像作为基础镜像。
- 它将API项目的已发布输出从计算机复制到容器中的/App文件夹。
- 它使用/App文件夹作为启动应用程序的位置。
- 它使用 Api.dll 运行dotnet命令以启动应用程序。
现在,在 API 文件夹内的命令提示符下运行docker build命令,以生成将包含API的新镜像:
docker build -t api .
现在,您应该在Docker Desktop中看到API的新镜像:
镜像就位后,现在可以使用具有以下参数的docker run命令运行API容器:
docker run -d -p 7000:80 -p 7001:443 ^
-e ASPNETCORE_URLS="https://+;http://+" ^
-e ASPNETCORE_HTTPS_PORT=7001 ^
-e ASPNETCORE_Kestrel__Certificates__Default__Password="" ^
-e ASPNETCORE_ENVIRONMENT=Container ^
-e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/api-server.pfx ^
-v %USERPROFILE%\.aspnet\https:/https/ ^
--network network-name ^
--network-alias api-server-name ^
--name api-container-name ^
api
参数指定:
- 计算机上的端口7000和7001分别映射到容器的端口80和443
- 计算机上的API端口为7001
- ASPNETCORE_Kestrel__Certificates__Default__Password参数指定API证书的密码,请确保在双引号内添加密码
- 该ASPNETCORE_ENVIRONMENT参数指定它将使用您之前创建的appsettings.Container.json配置文件
- ASPNETCORE_Kestrel__Certificates__Default__Path参数指定API证书的位置
- 该-v参数将容器中的/https/位置映射到计算机上具有API证书的%USERPROFILE%\.aspnet\https位置
- 该–network参数指定网络的名称,以便SQL服务器和UI容器可以找到API
- 该–network-alias参数指定API服务器的名称,这是UI容器可以找到API所必需的
- –name参数指定API容器的名称
现在,您应该看到在端口7001上运行的API容器:
您可以通过转到如下所示的 https://localhost:7001/api/customer 并注意到证书对您的浏览器不安全来查看API正在运行,这没关系,因为您的浏览器用localhost作为服务器的名称而不是证书中指定的API服务器的名称:
设置UI容器
对于UI容器,我们可以使用该dotnet dev-certs命令为localhost域生成证书,以便在您的浏览器上信任它。首先,通过运行以下命令清理计算机上可能已存在的现有证书:
dotnet dev-certs https --clean
然后运行以下命令,通过为其提供密码来生成新证书。密码必须是字母数字,否则将不起作用。
dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\ui.pfx -p password-here
通过转到用户配置文件位置下的目录来检查证书是否已生成:
然后运行以下命令以信任证书:
dotnet dev-certs https --trust
现在,让我们为UI创建一个镜像。首先,复制应用程序appsettings.Development.json 配置文件并将其命名为appsettings.Container.json,它将是容器的配置文件:
在应用程序设appsettings.Container.json文件,更新API的url位置:
"APIurl": "https://api-server-name/api/"
将UI项目发布到 bin 目录,然后选择如下所示的linux-x64目标运行时:
我们需要UI容器信任API证书,否则会出现错误“由于证书链中的错误,远程证书无效:不受信任的根”。我们可以将API证书添加到UI容器中并信任它。转到发布UI项目的 bin 目录,创建一个名为 cert 的文件夹,并将API证书(位于计算机上的%USERPROFILE%\.aspnet\https 中)复制到其中:
现在我们可以在UI项目中创建 Dockerfile,并告诉它信任API证书。下面是 Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:6.0
COPY bin/Release/net6.0/publish App/
ADD bin/cert/ /etc/ssl/certs
RUN update-ca-certificates
WORKDIR /App
ENTRYPOINT ["dotnet", "WebApp.dll"]
Dockerfile 指定:
- 将包含API证书的 bin/cert 内容添加到容器中的/etc/ssl/certs 位置
- 运行update-ca-certificates命令,该命令将信任在/etc/ssl/certs 中添加的新证书
现在,在WebApp文件夹内的命令提示符下运行docker build命令,以生成将包含UI的新镜像:
docker build -t ui .
现在,您应该在Docker Desktop中看到UI的新镜像:
现在,您可以使用具有以下参数的docker run命令运行UI容器:
docker run -d -p 8000:80 -p 8001:443 ^
-e ASPNETCORE_URLS="https://+;http://+" ^
-e ASPNETCORE_HTTPS_PORT=8001 ^
-e ASPNETCORE_Kestrel__Certificates__Default__Password="" ^
-e ASPNETCORE_ENVIRONMENT=Container ^
-e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/ui.pfx ^
-v %USERPROFILE%\.aspnet\https:/https/ ^
--network network-name ^
--network-alias ui-server-name ^
--name ui-container-name ^
ui
参数指定:
- 计算机上的端口8000和8001分别映射到容器的端口80和443
- 计算机上的UI端口为8001
- ASPNETCORE_Kestrel__Certificates__Default__Password参数指定UI证书的密码,请确保在双引号内添加密码
- 该ASPNETCORE_ENVIRONMENT参数指定它将使用您之前创建的appsettings.Container.json配置文件
- ASPNETCORE_Kestrel__Certificates__Default__Path参数指定UI证书的位置
- 该-v参数将容器中的 /https/ 位置映射到计算机上具有UI证书的%USERPROFILE%\.aspnet\https 位置
- 该–network参数指定网络的名称,以便UI容器可以找到API容器
- –network-alias参数指定UI服务器的名称
- –name参数指定UI容器的名称
现在应看到在端口8001上运行的UI容器:
并查看在端口8001上运行的UI,其中包含受信任的自签名证书:
一切启动并运行后,您可以创建一个名为 docker-compose.yml 的 Docker Compose 文件,其中包含所有docker run命令,以便您可以一次性创建所有三个容器(SQL Server、API、UI)。下面是此项目的Docker Compose文件,与docker run命令相比,语法应该是不言自明的。
version: "3.9"
services:
sql-server-container-name:
image: mcr.microsoft.com/mssql/server:2022-latest
ports:
- "1433:1433"
volumes:
- sql-server-volume-name:/var/opt/mssql
- ${USERPROFILE}\.aspnet\https:/https/
environment:
MSSQL_SA_PASSWORD: ""
ACCEPT_EULA: Y
networks:
network-name:
aliases:
- sql-server-name
api-container-name:
image: api
ports:
- "7000:80"
- "7001:443"
volumes:
- ${USERPROFILE}\.aspnet\https:/https/
environment:
ASPNETCORE_URLS: "https://+;http://+"
ASPNETCORE_HTTPS_PORT: 7001
ASPNETCORE_Kestrel__Certificates__Default__Password: ""
ASPNETCORE_ENVIRONMENT: Container
ASPNETCORE_Kestrel__Certificates__Default__Path: /https/api-server.pfx
networks:
network-name:
aliases:
- api-server-name
ui-container-name:
image: ui
ports:
- "8000:80"
- "8001:443"
volumes:
- ${USERPROFILE}\.aspnet\https:/https/
environment:
ASPNETCORE_URLS: "https://+;http://+"
ASPNETCORE_HTTPS_PORT: 8001
ASPNETCORE_Kestrel__Certificates__Default__Password: ""
ASPNETCORE_ENVIRONMENT: Container
ASPNETCORE_Kestrel__Certificates__Default__Path: /https/ui.pfx
networks:
network-name:
aliases:
- ui-server-name
volumes:
sql-server-volume-name:
networks:
network-name: {}
要运行docker compose文件,您可以给出以下命令:
docker compose up -d
https://www.codeproject.com/Articles/5348430/Deploying-Full-Stack-ASP-NET-Core-with-API-and-SQL