Asp-Net-Core Development Notes: Framework-Dependent Deployment Paired with Docker
Previously, I wrote an article about deploying AspNetCore applications using Docker. This approach is very convenient when combined with CICD. After the build, you push the image to a private DockerHub, and on the production server, you can pull the image and run it directly. However, sometimes a more traditional deployment method is needed, such as packaging the executable locally and then placing it directly on the server to run. Once this method is configured, each update only requires re-publishing locally and then uploading the executable.
目录7 个章节
Preface
Previously, I wrote an article about deploying an AspNetCore application using Docker. This method, combined with CICD, is very convenient—after building, you push to a private DockerHub, and on the production server, you simply pull the image and run it directly.
However, sometimes a more traditional deployment method is needed, such as packaging an executable locally and then placing it directly on the server to execute.
There are two ways to package an executable in .NetCore:
- Self-contained executable - Does not depend on any runtime environment; it can be started directly upon execution.
- Framework-dependent - Requires the corresponding version of the dotnet-runtime to be installed first to run.
While the former is convenient, the packaged file size is relatively large. It is said that there will be optimizations in .NET 8, but we’ll deal with that later. This article records the second method, framework-dependent, combined with Docker deployment, so there is no need to install the runtime on the server.
(PS: It feels a bit like Java deployment)
After configuring this method, each update only requires re-publishing locally, uploading the executable, and overwriting the version on the server. It’s very convenient~
Do Not Generate PDB
Each build generates a bunch of PDB debug files, but we don't need these files during deployment. You can disable them by configuring the .csproj file.
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
A better approach is to create a common.props file in the solution directory, place the above configuration in this file, and then have each .csproj file reference it. The specific path may vary depending on your actual situation.
<Import Project="../../common.props" />
Packaging
Use the following command to package
dotnet publish -f net7.0 -c Release -p:PublishSingleFile=true
After packaging, it generates an executable file that needs to depend on a runtime to run. Next, prepare the Docker configuration.
dockerfile
The official Dockerfile includes the entire workflow from source code building to deployment. Here we only need base and final, which means placing the executable into Microsoft's base image to run.
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM base AS final
WORKDIR /app
COPY . .
ENTRYPOINT ["./AIHub.Blazor"]
docker-compose
If you don't want to type a bunch of docker commands every time, or prefer not to write bash scripts, docker-compose is the best choice. It also makes it very convenient to use with other container orchestration tools.
version: '3.6'
services:
web:
image: ${DOCKER_REGISTRY-}web
container_name: aihub
restart: always
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://+:80
build:
context: .
volumes:
- .:/app
ports:
- "12001:80"
networks:
- default
- swag
networks:
swag:
name: swag
external: true
default:
name: aihub
Additional notes:
- The
portssection maps port 80 inside the container. - I am using swag to provide the web service, so technically, there's no need to use
portsfor port mapping. - I will later try using candy / traefik to replace nginx (this project does not use nginx; it uses kestrel directly).
Start!
Start using the command line!
docker compose up
If ports are not mapped, you will also need to configure a reverse proxy.
Swag Configuration
Here's the configuration
/path/to/swag/config/nginx/proxy-confs/aihub.subdomain.conf
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name aihub.*;
include /config/nginx/ssl.conf;
client_max_body_size 0;
# enable for ldap auth, fill in ldap details in ldap.conf
#include /config/nginx/ldap.conf;
# enable for Authelia
#include /config/nginx/authelia-server.conf;
location / {
# enable the next two lines for http auth
#auth_basic "Restricted";
#auth_basic_user_file /config/nginx/.htpasswd;
# enable the next two lines for ldap auth
#auth_request /auth;
#error_page 401 =200 /ldaplogin;
# enable for Authelia
#include /config/nginx/authelia-location.conf;
include /config/nginx/proxy.conf;
include /config/nginx/resolver.conf;
set $upstream_app aihub;
set $upstream_port 80;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
proxy_hide_header X-Frame-Options; # Possibly not needed after Portainer 1.20.0
}
}
_EOF_
Asp-Net-Core Development Notes: Framework-Dependent Deployment Paired with Docker
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
Asp-Net-Core开发笔记:Oracle调优
Supported Connection String Attributes To obtain an OracleConnection object in a .NET stored procedure that represents the implicit database connection, set the ConnectionString property of the Oracle
2023-03-05 · Asp-Net-Core开发笔记 · 约 1 分钟
Asp-Net-Core开发笔记:实现动态审计日志功能
审计日志不仅仅是一种遵循最佳实践的手段,更是确保数据安全、提高系统透明度、促进责任归属明晰的关键工具。
2024-03-21 · Asp-Net-Core开发笔记 · 约 1 分钟
Asp-Net-Core开发笔记:进一步实现非侵入性审计日志功能
现在已经可以实现对业务代码完全无侵入的审计日志了,在需要审计的接口上加上 `[AuditLog]` 特性,就可以记录这个接口的操作日志,还有相关的实体变化记录,还算是方便。
2024-04-29 · Asp-Net-Core开发笔记 · 约 1 分钟
AspNetCore开发笔记:WebApi项目集成企业微信和公众号
微信开发文档烂得离谱,直接用SKIT库搞定。异步处理消息,图片下载内存处理,公众号被动回复5秒内搞定。啧啧。
2025-12-22 · Asp-Net-Core开发笔记 · 约 1 分钟
讨论
共 0 条加载评论中…