使用 Docker Compose 进行 Docker 部署
本文档假设您倾向于使用 Blazor WebAssembly 作为 UI 框架,使用 MongoDB 作为数据库提供程序。对于其他选项,请更改本文档顶部的偏好设置。
本指南将引导您了解如何为您的应用程序构建 Docker 镜像并使用 docker compose 在本地运行。您将详细了解提供的构建脚本和 docker compose 文件,并学习如何为生产环境修改它们。
构建 Docker 镜像
每个应用程序都包含一个名为 Dockerfile.local 的 dockerfile 用于构建 Docker 镜像。顾名思义,这些 Dockerfile 不是多阶段 Dockerfile,需要以 Release 模式构建项目才能创建镜像。目前,如果您使用 CI & CD 流水线构建镜像,则需要在构建镜像之前将 SDK 包含到流水线中,或者添加您自己的多阶段 dockerfile。
由于它们不是多阶段 Dockerfile,如果您想单独构建镜像,可以导航到相关要托管的应用程序文件夹并运行以下命令:
dotnet publish -c Release
首先填充 Release 文件夹,该文件夹将用于构建 Docker 镜像。之后,您可以运行以下命令:
docker build -f Dockerfile.local -t mycompanyname/myappname:version .
来手动构建您的应用程序镜像。
为了简化流程,应用程序模板在 etc/docker-compose 文件夹下提供了一个构建脚本 build-images-locally.ps1,用于一键构建所有镜像。
根据您的应用程序名称、UI 和类型,将生成一个构建镜像脚本。
param ($version='latest')
$currentFolder = $PSScriptRoot
$slnFolder = Join-Path $currentFolder "../../"
Write-Host "********* 正在构建 DbMigrator *********" -ForegroundColor Green
$dbMigratorFolder = Join-Path $slnFolder "src/Acme.BookStore.DbMigrator"
Set-Location $dbMigratorFolder
dotnet publish -c Release
docker build -f Dockerfile.local -t acme/bookstore-db-migrator:$version .
Write-Host "********* 正在构建 Blazor 应用程序 *********" -ForegroundColor Green
$blazorFolder = Join-Path $slnFolder "src/Acme.BookStore.Blazor"
Set-Location $blazorFolder
dotnet publish -c Release -p:PublishTrimmed=false
docker build -f Dockerfile.local -t acme/bookstore-blazor:$version .
Write-Host "********* 正在构建 Api.Host 应用程序 *********" -ForegroundColor Green
$hostFolder = Join-Path $slnFolder "src/Acme.BookStore.HttpApi.Host"
Set-Location $hostFolder
dotnet publish -c Release
docker build -f Dockerfile.local -t acme/bookstore-api:$version .
### 全部完成
Write-Host "完成" -ForegroundColor Green
Set-Location $currentFolder
默认情况下,镜像标签设置为 latest。您可以在第一行更新 param $version 以将其设置为镜像的标签。
您可以在下面查看发布应用程序所需的所有 Dockerfile:
DBMigrator
DbMigrator 是一个控制台应用程序,用于迁移应用程序数据库并填充运行应用程序所需的重要初始数据。例如预定义的语言、管理员用户和角色、OpenIddict 应用程序和作用域。
此项目下提供的 Dockerfile.local 如下:
FROM mcr.microsoft.com/dotnet/aspnet:10.0
COPY bin/Release/net10.0/publish/ app/
WORKDIR /app
ENTRYPOINT ["dotnet", "BookStore.DbMigrator.dll"]
如果您不想使用 build-images-locally.ps1 来构建镜像,或者想单独手动构建此镜像,请导航到 DbMigrator 文件夹并运行:
dotnet publish -c Release # 以 Release 模式构建项目
docker build -f Dockerfile.local -t acme/bookstore-db-migrator:latest . # 使用 "latest" 标签构建镜像
Blazor
Blazor 应用程序使用 nginx:alpine-slim 基础镜像来托管 Blazor 应用程序。您可以根据自己的偏好修改 Dockerfile.local 中的基础镜像,该文件位于解决方案的 Blazor 文件夹下,如下所示:
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS build
COPY bin/Release/net10.0/publish/ app/
FROM nginx:alpine-slim AS final
WORKDIR /usr/share/nginx/html
COPY --from=build /app/wwwroot .
COPY /nginx.conf /etc/nginx/conf.d/default.conf
除了构建好的 Blazor 应用程序外,还有 nginx.conf 文件也被复制到应用程序镜像中。nginx.conf 文件:
server {
listen 80;
listen [::]:80;
server_name _;
#listen 443 ssl;
#server_name www.myapp.com;
#ssl_certificate www.myapp.com.crt;
#ssl_certificate_key www.myapp.com.key;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
#error_page 404 /404.html;
# 将服务器错误页面重定向到静态页面 /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
如果您不想使用 build-images-locally.ps1 来构建镜像,或者想单独手动构建此镜像,请导航到 Blazor 文件夹并运行:
## 以 Release 模式构建项目,并禁用修剪选项。您可以根据需要启用或配置它
dotnet publish -c Release -p:PublishTrimmed=false
docker build -f Dockerfile.local -t acme/bookstore-blazor:latest . # 使用 "latest" 标签构建镜像
Http.Api.Host
这是后端应用程序,也包含 OpenID 提供程序功能。dockerfile.local 位于 Http.Api.Host 项目下,如下所示:
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
COPY bin/Release/net10.0/publish/ app/
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
RUN dotnet dev-certs https -v -ep authserver.pfx -p 2D7AA457-5D33-48D6-936F-C48E5EF468ED
FROM base AS final
WORKDIR /app
COPY --from=build /src .
ENTRYPOINT ["dotnet", "Acme.BookStore.HttpApi.Host.dll"]
构建镜像时,您可能会遇到错误。这是因为 dotnet dev-certs 命令试图列出容器内的现有证书但无法访问。这个错误并不重要,因为我们的目标是生成 authserver.pfx 文件并丢弃构建它的容器。
由于它内部包含 openid 提供程序,它还使用多阶段来生成 authserver.pfx 文件,该文件被 OpenIddict 用作签名和加密证书。此配置位于 HttpApiHostModule 的 PreConfigureServices 方法中:
if (!hostingEnvironment.IsDevelopment())
{
PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
{
options.AddDevelopmentEncryptionAndSigningCertificate = false;
});
PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
{
serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", configuration["AuthServer:CertificatePassPhrase"]!);
serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!));
});
}
此配置禁用 DevelopmentEncryptionAndSigningCertificate,并使用名为 authserver.pfx 的自签名证书来签名和加密令牌。该证书是在构建 Docker 镜像时使用 dotnet dev-certs 工具创建的。它是一个示例生成的证书,并且建议为生产环境更新它。您可以查看 OpenIddict 加密和签名凭据文档 以了解不同的选项和自定义。
您始终可以使用 Dockerfile 之外的任何其他工具创建任何自签名证书。您需要记住将它们设置为嵌入式资源。
如果您不想使用 build-images-locally.ps1 来构建镜像,或者想单独手动构建此镜像,请导航到 Http.Api.Host 文件夹并运行:
dotnet publish -c Release # 以 Release 模式构建项目
docker build -f Dockerfile.local -t acme/bookstore-api:latest . # 使用 "latest" 标签构建镜像
在 Localhost 上运行 Docker-Compose
在 etc/docker-compose 文件夹下,您可以找到用于运行应用程序的 docker-compose.yml。为了简化运行过程,模板提供了 run-docker.ps1(和 run-docker.sh)脚本,用于处理环境变量中使用的 HTTPS 证书的创建;
$currentFolder = $PSScriptRoot
$slnFolder = Join-Path $currentFolder "../"
$certsFolder = Join-Path $currentFolder "certs"
If(!(Test-Path -Path $certsFolder))
{
New-Item -ItemType Directory -Force -Path $certsFolder
if(!(Test-Path -Path (Join-Path $certsFolder "localhost.pfx") -PathType Leaf)){
Set-Location $certsFolder
dotnet dev-certs https -v -ep localhost.pfx -p 91f91912-5ab0-49df-8166-23377efaf3cc -t
}
}
Set-Location $currentFolder
docker-compose up -d
run-docker.ps1(或 run-docker.sh)脚本将检查 etc/certs 文件夹下是否已存在开发证书,如果不存在,则生成 localhost.pfx 文件。Kestrel 将使用此文件作为 HTTPS 证书。
您也可以使用 dotnet dev-certs https -v -ep myCert.pfx -p YOUR_PASSWORD_FOR_HTTPS_CERT -t 或使用任何其他自签名证书生成工具,在不同路径手动创建 localhost.pfx 文件,使用不同的名称和密码。
您需要在 docker-compose.yml 文件中更新服务环境变量 Kestrel__Certificates__Default__Path 为您创建的路径和文件名,以及 Kestrel__Certificates__Default__Password 为您的新密码。
现在让我们分解 docker-compose.yml 文件中的每个 Docker compose 服务:
bookstore-blazor
services:
bookstore-blazor:
image: acme/bookstore-blazor:latest
container_name: bookstore-blazor
build:
context: ../../
dockerfile: src/Acme.BookStore.Blazor/Dockerfile.local
ports:
- "44307:80"
depends_on:
- bookstore-api
restart: on-failure
volumes:
- ./appsettings.json:/usr/share/nginx/html/appsettings.json
networks:
- abp-network
这是我们在 http://localhost:44307 上默认部署的 Blazor 应用程序,使用我们通过 build-images-locally.ps1 脚本构建的 acme/bookstore-blazor:latest 镜像。它没有使用 localhost.pfx 运行 HTTPS,因为它运行在 Nginx 上,并且不接受 pfx 文件作为 SSL。您可以查看 Nginx 配置 HTTPS 服务器文档 了解更多信息,并将必要的配置应用到 Blazor 文件夹下的 nginx.conf 文件。
更新
Blazor文件夹下的nginx.conf文件后,不要忘记重新构建acme/bookstore-blazor:latest镜像。
在 volumes 部分,它将 docker 文件夹下的 appsettings.json 文件挂载,以实现在不重新构建镜像的情况下更改环境变量。覆盖的 docker/appsettings.json 文件如下:
{
"App": {
"SelfUrl": "http://localhost:44307"
},
"AuthServer": {
"Authority": "https://localhost:44354",
"ClientId": "BookStore_Blazor",
"ResponseType": "code"
},
"RemoteServices": {
"Default": {
"BaseUrl": "https://localhost:44354"
},
"AbpAccountPublic": {
"BaseUrl": "https://localhost:44354"
}
},
"AbpCli": {
"Bundle": {
"Mode": "BundleAndMinify",
"Name": "global",
"Parameters": {
"LeptonXTheme.Layout": "side-menu"
}
}
}
}
此服务在名为
abp-network的 Docker 网络中运行,等待bookstore-api启动,并在失败时重新启动。您可以根据自己的偏好自定义这些编排行为。
bookstore-api
bookstore-api:
image: acme/bookstore-api:latest
container_name: bookstore-api
hostname: bookstore-api
build:
context: ../../
dockerfile: src/Acme.BookStore.HttpApi.Host/Dockerfile.local
environment:
- ASPNETCORE_URLS=https://+:443;http://+:80;
- Kestrel__Certificates__Default__Path=/root/certificate/localhost.pfx
- Kestrel__Certificates__Default__Password=91f91912-5ab0-49df-8166-23377efaf3cc
- App__SelfUrl=https://localhost:44354
- App__CorsOrigins=http://localhost:44307
- App__HealthCheckUrl=http://bookstore-api/health-status
- AuthServer__Authority=http://bookstore-api
- AuthServer__RequireHttpsMetadata=false
- ConnectionStrings__Default=mongodb://mongodb/BookStore
ports:
- "44354:443"
depends_on:
mongo-db:
condition: service_healthy
volumes:
- ./certs:/root/certificate
networks:
- abp-network
此服务是 Blazor 应用程序的后端应用程序,使用我们通过 build-images-locally.ps1 脚本构建的 acme/bookstore-api:latest 镜像。它默认运行在 https://localhost:44354,通过挂载我们在 etc/certs 文件夹下生成的自签名证书来实现。
App__SelfUrl指向我们暴露端口的 localhosthttps://localhost:44354。部署到生产环境时,必须指向真实的 DNS。App__CorsOrigins是 CORS 的覆盖配置。我们在此添加 angular 应用程序的 URLhttp://localhost:44307。部署到生产环境时,必须指向真实的 DNS。App__HealthCheckUrl是健康检查 URL 的覆盖配置。由于此请求将在内部完成,因此它指向容器化环境中的服务名称http://bookstore-api/health-statusAuthServer__Authority是颁发者 URL。http://bookstore-api是容器化的颁发者。部署到生产环境时,必须指向真实的 DNS。AuthServer__RequireHttpsMetadata是 openid 提供程序强制使用 HTTPS 的选项。 由于后端本身就是 OpenID 提供程序,默认情况下我们将其设置为true。ConnectionStrings__Default是被覆盖的默认连接字符串。它默认使用 容器化的 mongodb 服务 。
此服务在名为
abp-network的 Docker 网络中运行,等待 数据库容器启动,并在失败时重新启动。您可以根据自己的偏好自定义这些编排行为。
db-migrator
db-migrator:
image: acme/bookstore-db-migrator:latest
container_name: db-migrator
build:
context: ../../
dockerfile: src/BookStore.DbMigrator/Dockerfile.local
environment:
- OpenIddict__Applications__BookStore_Blazor__RootUrl=http://localhost:44307
- ConnectionStrings__Default=mongodb://mongodb/BookStore
depends_on:
mongo-db:
condition: service_healthy
networks:
- abp-network
数据库迁移器服务迁移数据库并填充初始数据。OpenIddict 数据是您的应用程序最重要的填充数据之一。在生产环境中,您需要覆盖应用程序的根 URL (http://localhost:44307) ,以便身份验证正常工作。
抠丁客



