首页 > 其他分享 >基于.NetCore开发博客项目 StarBlog - (31) 发布和部署

基于.NetCore开发博客项目 StarBlog - (31) 发布和部署

时间:2024-02-08 17:22:05浏览次数:27  
标签:NetCore 部署 StarBlog 31 dll proxy docker true

前言

StarBlog 第一期规划的功能基本完成了,我想着在春节前应该可以把第一期的系列文章完结掉,那么在差缺补漏阶段就剩下开发项目的最后一个环节——部署了。

PS: 事实上,还有一个很重要但又经常被略过的测试环节我们没有提到,因为时间关系,第一期规划我没有写单元测试和集成测试,在开发中,测试环节是必备的,我也立个flag会在之后补充这部分测试的代码。

关于 dotnet 的测试,可以看看我之前的这篇文章,有余力的同学可以先自行编写测试代码。

文章传送门: Asp-Net-Core学习笔记:单元测试和集成测试

C# 现在已经全面拥抱云原生跨平台,部署方式多种多样,特别是 dotnet8 出来之后大大加强了 AOT 功能,可以获得和 go 差不多的方便 AOT 能力,本文介绍几种常见的部署方式,可供读者灵活选择。

发布

发布就是把程序编译+打包成一个可执行文件的过程,一般使用 dotnet publish 或者 msbuild 命令,本文使用 dotnet publish

然后编译又有多种模式,一般分成这几种

  • Framework dependent (框架依赖) - 需要先安装对应版本的 runtime 才能执行,跟 Java 的 jar 包差不多
  • Self contained (自包含) - 自带运行时,可以直接执行,但跟框架依赖相比没有本质区别
  • AOT (Ahead of time) - 生成二进制文件,不需要运行时可以直接运行

第三种 AOT 是跟随着 dotnet8 退出新发布的(之前的不完善),目前对于 AspNetCore 项目来说还需要一些修改,本项目开发的时候还没有 AOT ,所以我们只用前两种方法,后续我会研究一下将 StarBlog 使用 AOT 方式发布。

框架依赖发布

使用命令

dotnet publish -r linux-x64 -c Release -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained false

参数说明:

  • -r linux-x64 - 表示使用 linux-x64 的 runtime ,如果要发布到其他平台,需要修改为对应的运行时,比如 win-x64
  • -c Release - 使用 Release 配置生成,相对的还有 Debug 模式,但只有开发才用
  • -p:PublishSingleFile=true - 生成单个文件,如果没有配置的话,会把项目里的依赖都带上,一大堆dll文件
  • -p:PublishTrimmed=true - 裁剪生成的文件,虽然项目的依赖很多,但使用到的 class 和 method 没有那么多,没用到的这部分就可以去掉,但如果项目里面大量用到反射,就要慎用这个功能,编译器可能没法检查到动态调用的方法

自包含发布

使用命令

dotnet publish -r linux-x64 -c Release -p:PublishSingleFile=true -p:PublishTrimmed=true  --self-contained true

会生成这些文件

 publish
 ├─ wwwroot
 ├─ words.json
 ├─ StarBlog.Web.xml
 ├─ StarBlog.Web
 ├─ SQLite.Interop.dll
 ├─ package.json
 ├─ package-lock.json
 ├─ Magick.Native-Q8-x64.dll.so
 ├─ Magick.Native-Q8-x64.dll.dylib
 ├─ Magick.Native-Q8-x64.dll
 ├─ libe_sqlite3.so
 ├─ appsettings.json
 ├─ appsettings.Development.json
 └─ appsettings-email.json

1 directory, 13 files

其中可执行文件就是 StarBlog.Web 这个,也就是我们的项目名称。

其他的都是一些配置啥的,然后还可以看到几个 dll,前面不是说把 dll 都打包到可执行文件里了吗,怎么还有?错啦,打包到一起的是那些纯 C# 实现的 dll ,里面是 IL 代码,而这里的 SQLite.Interop.dllMagick.Native-Q8-x64.dll 实际上是 C/C++ 之类开发的第三方库(native library),是二进制的形式,这部分默认不会包含到可执行文件里。

当然也可以集成到一起,加个参数就行 -p:IncludeNativeLibrariesForSelfExtract=true

本机部署 (supervisor)

最直接的部署方式,把程序发布为可执行文件,直接在服务器上运行,搭配 supervisor 等进程监控工具,也是我的博客目前使用的部署方式。

我之前已经写过关于部署的文章,可以参考一下: Asp-Net-Core学习笔记:5.构建和部署

使用 supervisor 来管理进程

首先安装

pip install supervisor

/etc/supervisord.d/ 下创建个配置,比如 star_blog.ini

内容如下,可以参考一下,运行起来后在 8080 端口访问

[program:star_blog]
# 脚本目录
directory = /home/apps/StarBlog
# 脚本执行命令
command = /home/apps/StarBlog/StarBlog.Web --urls "http://*:8080;"
# supervisor启动的时候是否随着同时启动,默认True
# 当程序exit的时候,这个program不会自动重启,默认unexpected,设置子进程挂掉后自动重启的情况,
# 有三个选项,false,unexpected和true。
# 如果为false的时候,无论什么情况下,都不会被重新启动,如果为unexpected,只有当进程的退出码不在下面的exitcodes里面定义的autorestart = true
autostart = true
# 这个选项是子进程启动多少秒之后,此时状态如果是running,则我们认为启动成功了。默认值为1
startsecs = 1
# 脚本运行的用户身份
user = hello

然后启动 supervisor

systemctl start supervisord.service

设置自启动

systemctl enable supervisord.service

不同的Linux发行版命令有所差别,可以自行查阅文档: https://github.com/Supervisor/supervisor

docker 部署

docker 部署的方式很灵活,可以在本地打包了镜像之后上传到仓库,服务器上 docker pull 拉下来部署,后续搭配流水线也很方便;也可以用我这种方式,docker 作为 runtime 环境,然后本地打包个框架依赖的可执行文件上传上去执行。

这里参考官方的模板里的 docker 部署方式,具体可以看我之前写的这篇文章: Asp-Net-Core开发笔记:FrameworkDependent搭配docker部署

根据前面的框架依赖发布,然后准备好 docker 配置,以后每次更新只需要上传可执行文件去覆盖就行了。

dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM base AS final
WORKDIR /app
COPY . .
ENTRYPOINT ["./StarBlog.Web"]

docker-compose.yaml

version: '3.6'

services:
  web:
    image: ${DOCKER_REGISTRY-}web
    container_name: starblog
    restart: always
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=http://+:80
    build:
      context: .
    volumes:
      - .:/app
    ports:
      - "8080:80"
    networks:
      - default

networks:
  default:
    name: starblog

启动

docker compose up

之后在 8080 端口可以访问

流水线部署

流水线可以实现自动部署,解放双手。

关于这部分本文就不赘述了,具体的我之前也写过文章,感兴趣的同学可以看看

其他注意事项

使用 Nginx 反向代理或者在 docker 内部正确获取 IP

本项目具有访问记录功能,如果使用了 nginx 反向代理或者在 docker 部署且没有正确配置的话,访客的IP地址会是 127.0.0.1 ,需要配置一下。

Nginx配置

server {
    listen        80;
    server_name   example.com *.example.com;
    location / {
        proxy_pass         http://127.0.0.1:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

后端配置中间件

app.UseForwardedHeaders(new ForwardedHeadersOptions {
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

搞定

小结

部署这块老生常谈了,多种方式各有优劣,这次急着收拾东西就不写太多了~

参考资料

标签:NetCore,部署,StarBlog,31,dll,proxy,docker,true
From: https://www.cnblogs.com/deali/p/18011965

相关文章

  • CF231E 题解
    本文采用CCBY-NC-SA4.0协议发布。前言提供一个圆方树做法。孩子圆方树学傻了,忘了还有缩点这回事。正文建圆方树。考虑一条圆方树上的路径,哪些点对答案有贡献:方点,这表示路径经过一个环,方案数\(\times2\).旁边有方点的圆点。这表示走到这时可以选择在环上绕一圈,方......
  • 今天回顾-回溯算法-131. 分割回文串
    注意点&感悟:对这个范围还是没太梳理清楚,我的感觉是当前位置是start_index,每轮的结束是i所以范围是[start_index,i+1]题目链接:131.分割回文串自己独立写的代码:classSolution:defpartition(self,s:str)->List[List[str]]:res=[]self.back......
  • 牛客周赛 Round 31
    牛客周赛Round31小红小紫替换代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<ll,ll>;#definefifirst#definesesecondusingi128=__int128_t;usingpiii=pair<ll,pair<ll,ll>>;voidsolve(){......
  • 【2024潇湘夜雨】WIN11_Pro_23H2.22635.3139软件选装纯净版2.04
    【系统简介】=============================================================1.本次更新母盘来自WIN11_Pro_23H2.22635.3139.2.增加部分优化方案,手工精简部分较多。3.OS版本号为22635.3139。精简系统只是为部分用户安装,个别要求高的去MSDN下。4.集成《DrvCeo-2.16.0.0》网卡版、运......
  • 牛客周赛31
    A小红小紫替换https://ac.nowcoder.com/acm/contest/74362/A这题相当于签到题只需要将kou的情况转换成yukari就行其他不变点击查看代码#include<bits/stdc++.h>usingnamespacestd;intmain(){stringa;cin>>a;if(a=="kou")cout<<"yukari"......
  • 牛客周赛 Round 31(A~F)
    目录ABCDEFA#include<bits/stdc++.h>#defineintlonglong#definerep(i,a,b)for(inti=(a);i<=(b);++i)#definefep(i,a,b)for(inti=(a);i>=(b);--i)#definepiipair<int,int>#definepllpair<longlong,longlong>#de......
  • 牛客周赛 Round 31(很菜的小白)
    A.小红小紫替换思路:签到题,字符串如果是kou就替换成yukari取余不变解法:无Code:#include<bits/stdc++.h>usingnamespacestd;intmain(){strings;std::cin>>s;std::cout<<(s=="kou"?"yukari\n":s)<<'\n&#......
  • [MY-013183] [InnoDB] Assertion failure: dict0dict.cc:1869:table->get_ref_count()
    背景:执行altertableTABLE_NAMEdroppartitionPART_NAME;时执行过程中执行了ctrl+c导致mysql服务器崩溃自动重启。mysql错误日志内容:2024-02-02T10:30:32.424737+08:00460639464[ERROR][MY-013183][InnoDB]Assertionfailure:dict0dict.cc:1869:table->get_ref_count......
  • FastAPI学习-31 FastAPI 如何集成 socket.io
    前言socket.io就是基于websocket封装的一个库,主要特点是能够进行实时的双向通讯,主要应用场景有实时的聊天,数据实时分析,数据传输,文件协同合作。有个socket.io的fastapi-socketio官方库,该库依赖传统的python-socketio库环境准备pipinstallfastapi-socketiofastapi服务端代码......
  • 2024.1.31 总结
    上午接到姜\(sir\)通知后就开始召集讲题组并开始写题解。\(B\)属于结论题,题解和我赛时的结论不一样,然后就都证明了一下。Link\(D\)有一点难,借鉴了Register_int的题解,\(dp\)那段卡了一小段时间。Link晚上吴队讲题(实验舱\(06\))\(A\)其实很简单,只需要统计奇数度数的点,最......