Dotnet 本地部署包快速构建为Docker镜像

目录说明
镜像构建目录
本地已经安装Docker,笔者使用的wsl 安装 Ubuntu22.04,对应Docker 版本为28.4.0,具体细节可以查看笔者的文章Docker在Linux中离线部署,同时保证本地已经包含镜像mcr.microsoft.com/dotnet/aspnet:9.0-alpine3.22,案例项目为.Net9.0 框架版本,官方镜像选择的aspnet:9.0-alpine3.22。
镜像构建时,目录如下,主要用于规范构建逻辑。
docker-build/
|--app/ # 后端部署包,其中wwwroot、logs为空文件夹不包含文件
|--.dockerignore# docker忽略文件
|--Dockerfile # 镜像构建配置文件
需要注意的是,项目部署包的发布配置如下:

容器运行目录
本地也需要安装docker-compose,并不是docker自带,安装过程同样可以查看笔者的文章Docker在Linux中离线部署,Docker-Compose 主要用于简化按照镜像构建目标容器,并实现一键配置网络、数据卷、服务端口等。
docker-compose/
|--config/ # 配置目录
|----appsettings.Development.json # development环境配置
|----appsettings.json # 默认配置
|--logs/ # 用于未来日志输出备用[可选]
|--resources/ # 挂载到wwwroot
|--.env # 环境变量
|--docker-compose.yml # compose配置
容器内外关系
为了方便对镜像、docker-compose配置以及容器不是很熟悉的读者能够更好的理解几者之间的关系,笔者梳理梳理出一个简单的关系图用于说明目录、文件以及网络的关系,运行时,默认情况下,net9.0 中默认运行监听服务端口为8080,这与一些低版本net 容器中为80端口不太一样需要特别注意,如无必要,建议不做修改,默认运行为Production 环境,可通过运行时环境变量进行修改。

部署说明
案例项目说明
案例项目为一个基础的WebApi 模板项目,包含一个天气Api、index.html、Development 环境可访问的Swagger 页面,对应依赖如下。
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.11" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="9.0.6" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.0.0" />
</ItemGroup>
</Project>
主类Program代码
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
//注册服务
builder.Services.AddSwaggerGen();
builder.Services.AddControllers();
var app = builder.Build();
//启动静态文件中间
app.UseStaticFiles();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
#region Swagger中间件相关
//添加swagger配置,并启动中间件
app.UseSwagger();
//启用Swagger-ui中间件,并配置swagger json的请求终节点
app.UseSwaggerUI();
#endregion
}
app.MapControllers();
app.Run();
}
}
运行项目时,浏览器访问http://ip:port/index.html输出如下:

访问http://ip:port/swagger/index.html 输出如下:

部署目录说明
发布包目录如下,执行程序为WebApplication1,也可以直接执行dotnet ./WebApplication1.dll。

基础镜像说明
微软官方提供了对应的运行时镜像,可以按照自己的需求去到镜像仓库进行版本查看。当前使用的aspnetcore,查看基础镜像构建Dockerfile 内容可以发现,实际直接使用的 aspnetcore 运行时。
ARG REPO=mcr.microsoft.com/dotnet/runtime
# Installer image
FROM $REPO:9.0.11-alpine3.22-amd64 AS installer
# Retrieve ASP.NET Core
RUN aspnetcore_version=9.0.11 \
&& wget \ https://builds.dotnet.microsoft.com/dotnet/aspnetcore/Runtime/$aspnetcore_version/aspnetcore-runtime-$aspnetcore_version-linux-musl-x64.tar.gz \
https://builds.dotnet.microsoft.com/dotnet/checksums/$aspnetcore_version-sha.txt \
&& awk -v file="aspnetcore-runtime-$aspnetcore_version-linux-musl-x64.tar.gz" '{gsub(/\r/, "")} $2 == file' $aspnetcore_version-sha.txt | sha512sum -c \
&& mkdir --parents /dotnet \
&& tar --gzip --extract --no-same-owner --file aspnetcore-runtime-$aspnetcore_version-linux-musl-x64.tar.gz --directory /dotnet ./shared/Microsoft.AspNetCore.App \
&& rm \
aspnetcore-runtime-$aspnetcore_version-linux-musl-x64.tar.gz \
$aspnetcore_version-sha.txt
# ASP.NET Core image
FROM $REPO:9.0.11-alpine3.22-amd64
# ASP.NET Core version
ENV ASPNET_VERSION=9.0.11
COPY --from=installer ["/dotnet", "/usr/share/dotnet"]
构建镜像
Docker及配置
.dockerignore 作为构建镜像时,本地docker 客户端进行传输忽略的文件配置清单,内容如下:
.git
Dockerfile
README.md
*.md
构建镜像需要 Dockerfile 文件进行镜像构建配置,对应构建Dockerfile文件内容如下。
# 使用官方的 ASP.NET Core 基础镜像
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine3.22 AS final
WORKDIR /app
# 将本地发布文件复制到镜像中
COPY ./app ./
ENTRYPOINT ["dotnet","./WebApplication1.dll"]
有了上述前置准备工作和相关文件,就可以进行镜像构建过程。切换会话到docker-build目录,进行构建命令。
sudo docker build . -t [自定义镜像名称]:[版本号]
当前笔者构建命令如下:
sudo docker build . -t webapi:0.0.1
输出结果如下,表示构建成功,可以在镜像中看到对应镜像。
Sending build context to Docker daemon 1.465MB
Step 1/4 : FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine3.22 AS final
---> 5786a890a61b
Step 2/4 : WORKDIR /app
---> Running in 7f88eca13bfa
---> Removed intermediate container 7f88eca13bfa
---> 44155dfbe259
Step 3/4 : COPY ./app ./
---> 32fac1b9a69e
Step 4/4 : ENTRYPOINT ["dotnet","./WebApplication1.dll"]
---> Running in 764a683c2895
---> Removed intermediate container 764a683c2895
---> a77b6be59a17
Successfully built a77b6be59a17
Successfully tagged webapi:0.0.1
查看镜像。
$ sudo docker images |grep webapi
webapi 0.0.1 a77b6be59a17 50 seconds ago 116MB
构建容器
Docker-Compose及配置
.env 可以存储作为docker-compose.yml 使用的自定义环境变量,docker-compose.yml 使用时为${APP_ROOT},当前表示容器数据卷所在宿主物理路径。
APP_ROOT=/home/ggcy/docker_data/webapi/docker-compose
对应docker-compose.yml 内容如下:
version: '3.8'
services:
server:
image: webapi:0.0.1
container_name: webapi-service
#restart: unless-stopped
# networks:
# - internal_network
ports:
- "8001:8080"
environment:
- ASPNETCORE_ENVIRONMENT=Development
volumes:
- ${APP_ROOT}/resources:/app/wwwroot
- ${APP_ROOT}/logs:/app/logs
- ${APP_ROOT}/config/appsettings.json:/app/appsettings.json
- ${APP_ROOT}/config/appsettings.Development.json:/app/appsettings.Development.json
# networks:
# internal_network:
# external: true
其中resources 中包含index.html;切换会话到docker-compose 目录执行如下命令,为方便查看并未设置-d 用于后台运行。
$sudo docker-compose up
[+] Running 1/1
✔ Container webapi-service Recreated 0.1s
Attaching to webapi-service
webapi-service | info: Microsoft.Hosting.Lifetime[14]
webapi-service | Now listening on: http://[::]:8080
webapi-service | info: Microsoft.Hosting.Lifetime[0]
webapi-service | Application started. Press Ctrl+C to shut down.
webapi-service | info: Microsoft.Hosting.Lifetime[0]
webapi-service | Hosting environment: Development
webapi-service | info: Microsoft.Hosting.Lifetime[0]
webapi-service | Content root path: /app
单独开启一个会话,查看对应容器运行情况,可以查看到容器运行正常。
$sudo docker ps|grep webapi-service
74ae4f5771c8 webapi:0.0.1 "dotnet ./WebApplica…" About a minute ago Up About a minute 0.0.0.0:8001->8080/tcp, [::]:8001->8080/tcp webapi-service
此时可以在服务运行会话中,ctrl+C 退出,然后再执行docker-compose up -d用于后台运行。
$sudo docker-compose up -d
[+] Running 1/1
✔ Container webapi-service Started
运行效果
浏览器访问http://localhost:8001/index.html,内容如下:

访问http://localhost:8001/swagger/index.html,输出结果如下:

更多推荐
所有评论(0)