本文有配套视频:
https://www.bilibili.com/video/av58096866/?p=9
一、部署
1、WIN_独立部署
感谢群里(白云)小伙伴,博主 @小淋科技 提出的方案(需要 netcore2.1+ ),我竟然忽略了,该打该打,官档都读不仔细,果然三人行必有我师!
微软官方文档 ——《独立部署 (SCD)》,使用这个方法很简单,只需要部署的时候,选择指定的平台,就可以不用安装其他,比如运行时、托管、SDK等,不过这样的话,可能下文的命令行操作不适用,不过还是很好很简单的方案,欢迎尝试。
2、WIN_IIS 部署,前后端不同站点
为了能有一个全新的环境,我还特地新买一台服务,要做好部署的准备,就必须要先进行初始化操作,也就是先准备好我们用到的原材料:
在服务器开启 IIS 就不多说了,相信每一个 Dotnet 开发者百分比必须要会的,其他的操作流程请看下边的步骤,具体的看动图:
先给自己的两个站点想好端口,比如我想的:core(1001端口)、Vue(1002端口)
0、编译项目,保证代码没问题,并配置 CORS 跨域服务;//下边动图中没有配置CORS,大家自己要注意 ①、发布项目;//请注意我的 publish 路径是 bin/Debug/netcore3.0,因为这样肯定不会漏掉文件!!! ②、拷贝到服务器指定文件夹; ③、IIS 添加站点;// 端口 1001 ④、修改应用程序池为“无托管”;//这也是为啥要安装 windows hosting 的原因 ⑤、安装 windows hosting(服务托管);//这是一个捆包,已经包含 Runtime(下载地址见下文 错误码 500.19 的解决方案中) ⑥、检查是否有指定的 Runtime(运行时); ⑦、重启项目,查看是否正常;http://localhost:1001/ // Vue 部分 ①、Build 项目; ②、拷贝到服务器指定文件夹; ③、IIS 添加站点;// 端口 1002 ④、运行项目,查看是否正常;http://localhost:1002/
修改好 hash 模式后,就成功了,注意要在 Core 项目中配置 CORS 跨域:
c.AddPolicy("LimitRequests", policy => { // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的 // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的,尽量写两个 policy .WithOrigins("http://127.0.0.1:1002", "http://localhost:1002") .AllowAnyHeader() .AllowAnyMethod(); });
最终结果如下:
3、WIN_IIS 部署,前后端一个站点
从上边的过程中,可以看出来还是比较简单的,一气呵成,行云流水,不过可能自己操作的时候会出现这样那样的问题,毕竟我也是给很多小伙伴都部署过,没有上百,也有五十次了,如果你有错误,请看我文章下边第二章的 常见错误 ,找到你遇到的错误。
上边的操作中,我们是把两个项目部署到了 IIS 中的不同站点,当然,我们也可以部署到一个站点,这样的话,就是一个域名了,但是丝毫没有影响我们分开开发,我们前后端攻城狮还是和以前一样的开发,只是将发布的文件上传到指定服务器文件夹中就行了。
操作步骤和上边的其实是几乎一样的,只不过我们不需要配置 CORS 跨域了,因为是同一个站点,且是只需要一个端口号,我们定为 1003端口
4、WIN_Git_Nginx_Kestrel 部署
上边的 IIS 部署咱们说完了,大家发现,存在一些问题:
1、过分的依赖 IIS,并没有完完全全的达到跨平台的目的;
2、操作步骤偏多,还需要拷贝文件,并且一个都不能少;
3、因为 IIS 会存在占资源的问题,每次如果我们更新 Blog.Core.dll 文件,都需要关闭站点,然后更新,再启动;
那接下来咱们就说说如何使用 Nginx+Kestrel 来简单的解决这些问题,步骤如下:
这里需要安装 Nginx (http://nginx.org/en/download.html)、Git(https://git-scm.com/downloads)、SDK(http://go.microsoft.com/fwlink/?LinkID=287120),过程省略,大家自行安装,这里我们把端口定为,NetCore(1004端口)、Vue(1005端口)
①、执行 Blog.Core.Build.bat 文件;// 主要是 git pull ,dotnet build 和 dotnet run ②、Nginx 代理服务,将 8081 端口,代理到 1004;//具体的代码在下边 ③、查看是否正常;// http://localhost:1004/ // Vue 部分 ①、执行 BS 命令;// cnpm run BS,这里是我自己的命令,主要是git pull 和 build ②、Nginx 代理 Vue 服务,并配置跨域,代理到1005;//具体的代码在下边 ③、查看是否正常;// http://localhost:1005/
大家可以看看,或者直接感受一下,这种部署方案,和 IIS 的方案,哪一个更好一些?三步走,也是很简单,而也很直观的。
从上边的部署中,我们可以看到,过程中我们几乎都没有进行什么配置,或者说都是一次性的配置,比如 Git 安装,比如 Nginx 的学习,只要我们配置了一次,以后多个项目就可以很快的操作了,比 IIS 每一个都要 Publish 并且各种配置来的快些。
不仅如此,我们也换掉了 IIS ,使用了 netcore 自带的 Kestrel 应用服务器,并且不会出现任何不同步的问题,只要你本地调试好代码,并 push 到 git 上!
5、WIN 部署到 Windows 服务
微软有提供 如何在windows服务托管asp.net core ,不过步骤比较麻烦,还需要改源码,网上找到一种方法 使用NSSM把.Net Core部署至windows服务
简单说一下步骤
1. 下载nssm:http://www.nssm.cc/download
2. 运行cmd,定位到nssm.exe文件路径,运行nssm install
3. 在弹出的窗口配置:
Path:dotnet所在的目录,一般默认是在C:\Program Files\dotnet\dotnet.exe;
Startup directory:程序所在的目录,就是最后程序dll所在的目录;
Arguments:程序dll的名称,一般是项目名加上.dll;
Service name:在此写上服务的名称即可。
最后点击install service 完成windows服务安装。
在windows服务找到对应服务名,启动,然后根据launchSettings.json配置的端口访问,即可调取接口。
4. 如果使用Nginx代理的话,注意端口是5000,不是8081
感谢博友 @小雪转中雪 提醒
6、Linux_Ubuntu_Nginx 部署
1、安装.NET Core
首先需要安装.NET Core Runtime: https://www.microsoft.com/net/download
点击之后,根据您的Linux发行版不同,选择相应的操作步骤:
最后执行dotnet --info验证安装是否成功:
2、安装Nginx
另外还需要安装Nginx,
安装好后,直接访问你的 IP 地址,如果看到如下效果说明安装成功:
修改 nginx.conf 配置代理:
修改后,重启:
3、在服务器构建源码并发布
然后就是发布程序了,发布有两种办法:
在开发机上执行 dotnet publish 然后把发布的文件远程到服务器上
直接在服务器上使用源码构建并发布,我一般是这样做的。
如果直接在服务器上构建发布,所以需要安装.NET Core SDK:https://www.microsoft.com/net/learn/get-started-with-dotnet-tutorial
然后就可以使用发布命令了:dotnet publish --configuration Release。
发布好的文件在 bin/Release/netcoreapp*.*/publish 下面。
再把publish下的所有文件复制到我的目标文件夹即可:
在我的目标目录下,有这些文件:
如果执行 dotnet test.dll,这个程序就会在localhost:5000运行:
4、配置Nginx
然后我们再回来配置Nginx,进入 /etc/nginx/sites-available ,里面有一个Default文件,把它改个名,然后我们再建立一个新的Default文件:
保存后执行 sudo nginx -t 检验这个配置文件。
然后再执行 nginx -s reload 来重启nginx。
随后需要再把发布后的程序运行一下:dotnet test.dll:
在我使用网址访问80端口的时候,会自动跳转到 https//localhost:5001端口,导致连接失败:
可以在开发的时候,就直接去掉项目中使用 https 地址就行,在 launchSettions.json 文件中:
或者禁用 https 中间件:
http://yourdomian.com/swagger/index.html
5、守护进程
在/etc/systemd/system 下新建文件(推荐使用winscp),文件名以.service结尾,配置内容为(注意:中文注释需要删掉,否则部分 Linux 服务器会报错):
写完配置文件后保存,输入指令确认服务:
systemctl enable (你的服务名).service
例如:systemctl enable HZKJ.service;
然后启动服务 systemctl start HZKJ.service
然后查看一下服务状态:systemctl status HZKJ 出现状态说明服务运行正常。
( 借鉴:https://www.cnblogs.com/Tassdar/p/9587829.html )
7、Linux_CentOs_Nginx 部署
1、安装.NET Core Runtime
首先需要安装.NET Core Runtime: https://dotnet.microsoft.com/download/linux-package-manager/centos/runtime-current
点击之后,根据您的Linux发行版不同,选择相应的操作步骤:
最后执行dotnet --info验证安装是否成功:
2、安装Nginx
另外还需要安装Nginx,
sudo yum install nginx
安装完成后,启用并启动Nginx服务:
sudo systemctl enable nginx
sudo systemctl start nginx
启动成功后,直接访问你的 IP 地址,如果看到如下效果说明安装成功:
3、Ftp将本地发布后的项目,打包上传到服务器
1、发布的过程,省略。
2、上传
3、上传成功,检查服务器是否存在
在我的目标目录下,有这些文件:
如果执行 dotnet Blog.Core.dll,这个程序就会在localhost:8081运行:
4、配置Nginx
修改 nginx.conf 配置代理:
然后我们再回来配置Nginx,进入 /etc/nginx,然后 vi 修改nginx.conf ,保存
如果不会操作 Linux ,请查看我的这个文章:http://tibug.neters.club/details/68
upstream dotnetblogserver3 { server 127.0.0.1:8081; } server { listen 8082;#请注意,我的项目现在启动的时候已经是 8081 了,这里就不要再监听8081了,会报错,随便找个其他的端口 server_name localhost; location /{ proxy_pass http://dotnetblogserver3; index index.html index.htm; } location = /50x.html { root html; } }
修改后,重启 nginx:
然后执行 nginx -s reload 来重启nginx。
随后需要再把程序运行一下:dotnet Blog.Core.dll 然后访问我们的 ip:8081 地址。
成功:(临时服务器,应该过期了)
http://62.234.167.243:8082/
5、守护进程
在/etc/systemd/system 下新建文件(推荐使用winscp),文件名以.service结尾,配置内容为(注意:中文注释需要删掉,否则部分 Linux 服务器会报错):
[Unit]
Description=HZKJ #服务描述,随便填就好 [Service]
WorkingDirectory=/website/HZKJ #工作目录,填你应用的绝对路径
ExecStart=/usr/bin/dotnet /website/HZKJ/CZKJ.CMS.Web.dll #启动:前半截是你dotnet的位置(一般都在这个位置),后半部分是你程序入口的dll,中间用空格隔开
Restart=always
RestartSec=25 #如果服务出现问题会在25秒后重启,数值可自己设置
SyslogIdentifier=HZKJ #设置日志标识,此行可以没有
User=root #配置服务用户,越高越好
Environment=ASPNETCORE_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.target
写完配置文件后保存,输入指令确认服务:
systemctl enable (你的服务名).service 例如:systemctl enable HZKJ.service; 然后启动服务 systemctl start HZKJ.service 然后查看一下服务状态:systemctl status HZKJ 出现状态说明服务运行正常。
( 借鉴:https://www.cnblogs.com/Tassdar/p/9587829.html )
8、Linux_Docker 部署
1、docker安装
第一种方案:
依次执行下列命令
sudo yum install -y yum-utils device-mapper-persistent-data lvm2 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sudo yum makecache fast sudo yum -y install docker-ce
第二种方案(绿色的部分):
Install using the repository
Before you install Docker Engine - Community for the first time on a new host machine, you need to set up the Docker repository. Afterward, you can install and update Docker from the repository.
SET UP THE REPOSITORY
Update the
apt
package index:$sudo apt-get update
Install packages to allow
apt
to use a repository over HTTPS:$sudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg-agent \software-properties-common
Add Docker’s official GPG key:
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Verify that you now have the key with the fingerprint
9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
, by searching for the last 8 characters of the fingerprint.$sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu \$(lsb_release -cs)\stable"
INSTALL DOCKER ENGINE - COMMUNITY
Update the
apt
package index.$sudo apt-get update
Install the latest version of Docker Engine - Community and containerd, or go to the next step to install a specific version:
$sudo apt-get install docker-ce docker-ce-cli containerd.io
Got multiple Docker repositories?
If you have multiple Docker repositories enabled, installing or updating without specifying a version in the
apt-get install
orapt-get update
command always installs the highest possible version, which may not be appropriate for your stability needs.To install a specific version of Docker Engine - Community, list the available versions in the repo, then select and install:
a. List the versions available in your repo:
查看详细的命令,可以去官网来安装:https://docs.docker.com/install/linux/docker-ce/ubuntu/
第三种方案:
如果你Linux系统是 Ubuntu 版本的,发现不能使用 yum 的话,可以使用 wget:
安装成功后,可以启动服务
检查docker是否安装成功:
docker version
若成功显示如下:
完成之后,我们来使用docker来测试一下HelloWorld,通过输入 docker pull hello-world 来拉取 hello-world 镜像
root@VM-0-3-ubuntu:~# docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:41a65640635299bab090f783209c1e3a3f11934cf7756b09cb2f1e02147c6ed8
Status: Downloaded newer image for hello-world:latest
这样我们就从仓库拉取到了HelloWorld的镜像,接下来我们来运行一下,通过输入docker run hello-world
到这里,我们的 Linux 系统下 Docker 环境已经正式配置成功,下边就是要正式部署我们的项目了。
2、Docker 部署
如果你有任何Docker部署的问题,可以联系群友 @赵岩(305353941) ,专业的。
2.1、上传文件到 linux 服务器
在 linux 下创建文件夹 BlogCoreAPI
用 ftp 把发布的文件全部上传到 BlogCoreAPI
2.2、添加 Dockerfile 文件
进入目录 BlogCoreAPI
cd BlogCoreAPI
创建文件 Dockerfile
vim Dockerfile
内容如下,说明:镜像里创建 blogcore 文件夹,复制 linux 上的文件到镜像目录,对外暴露 8101 端口,运行程序
FROM microsoft/aspnetcore:2.2 RUN cd /usr/local/src RUN mkdir blogcore WORKDIR /usr/local/src/blogcore COPY *.* ./ EXPOSE 8101 CMD ["dotnet", "Blog.Core.dll"]
保存
2.3、构建镜像
镜像名字叫 blogcore-image,禁用缓存,否则迭代时会出问题
docker build --no-cache -t blogcore-image . //注意这个点 . 表示当前目录
2.4、运行容器
用镜像 blogcore-image 创建容器,指定容器名称是 blogcore-container,指定时区(默认是美国时间,相差8小时)
docker run --name=blogcore-container -dp 8101:8101--restart=always -e LC_ALL="en_US.UTF-8" -e TZ="Asia/Beijing" blogcore-image //修改默认时区到亚洲/北京,并且将容器里的 8101 端口映射到 linux 主机的 8101 端口,最后每次运行失败后自动重启
如果你想要查看刚刚创建的容器的时区是否成功,可以执行命令:
docker exec blogcore-container date //查询当前容器时区
打开浏览器访问试试:http://yourdomian.com/swagger/index.html
热心博友提供知识:@ Mr七师弟 的提醒:
提一个docker下的部署方法吧,
2.5、发布更新
上面说的是第一次发布,后期迭代,需要把容器删除,再构建镜像,运行容器。
2.5.1 删除容器
docker container rm -f cchr-container
2.5.2 构建镜像&运行容器
就和上边的一样了:
docker build --no-cache -t cchr-image .
docker run --name=blogcore-container -dp 8101:8101--restart=always -e LC_ALL="en_US.UTF-8" -e TZ="Asia/Beijing" blogcore-image
我还不知道有没有更快的方法,欢迎提建议。
9、PM2 做进程管理
待补充。
二、NetCore 错误
下边的都是我平时遇到的常见的错误,如果大家还有其他错误,可以留言下来,我补充到文章中,让更多的小伙伴都看到,避免麻烦。
1、错误码 —— 500.00
解析:发布后启动失败,进程内,网友提供,暂时我还没遇到
方案:
方法1:
应用池高级配置 - 启动32位应用程序 - 设置为True
方法2:
web.config
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" startupTimeLimit="3600" requestTimeout="23:00:00" hostingModel="InProcess">
删除 hostingModel="InProcess"
2、错误码 —— 500.19
解析:未安装 windows 服务器托管,打不开当前项目的 模块 选项
方案:
安装和项目匹配的 服务器托管( windows hosting ),这个是捆绑的可执行文件,除了托管,也把x86 和 x64的运行时都一起安装好了。
地址:https://dotnet.microsoft.com/download/thank-you/dotnet-runtime-3.0.0-windows-hosting-bundle-installer
3、错误码 —— 500.21
解析:没有安装指定的模块,如果你想问这个模块是在项目哪里写的,可以查看发布后的 web.config 文件
方案:
1、如果你没有安装上边的 windows-hosting ,直接安装就可以解决这个问题;
2、如果已经安装了服务器托管,发现还没有这个 V2 模块,就是你项目的问题了,这个时候你可以从本地再发布 publish 一次,然后拷贝到服务器即可。
但是,如果还没有的话,证明你本地开发的项目异常了,不过这个情况基本可以排除,只要是 SDK 3.0 开发的,本地
最终要确保 AspNetCoreModuleV2 模块被安装。
4、错误码 —— 500.30
解析:进程内失败,这个我没有遇到,有群里小伙伴说的。
方案:
1、检查检查是否安装了 host
5、错误码 —— 502.5
解析:1、没有安装指定的运行时,进程外启动失败。
2、还有可能是在发布的时候,缺少某些依赖dll文件,可以打开日志调试,请看下边第七条。
3、或者使用 dotnet 命令行查看,是否有错误信息在控制台出现。
方案:
安装指定版本的 Runtime 运行时。
一般情况下,只要安装了服务器托管的话,会自动安装对应版本的运行时,但是有时候安装好了,还是会遇到这个错误,是因为我们后期项目迭代升级了:
举个栗子,本来我们的项目是 Netcore 2.2 版本,后来更新到了 3.0 ,但是服务器的运行时还是旧的 Runtime 2.2 运行时,我们把代码部署到服务器,发现没有指定运行时,就会出现这个问题。
下载地址:https://dotnet.microsoft.com/download/dotnet-core/3.0
2、感谢网友提供资料:@疯言
502.5 另一种错误原因 一般缺少了Blog.Core.Repository.dll 和 Blog.Core.Services.dll
6、错误码 —— 503
解析:IIS 项目应用程序池未开启
方案:开启程序池即可,
但是经过测试发现,不使用 “无托管代码” 也可以,这是为什么,很好奇?
7、An error occurred while starting the application
解析:项目已经可以启动,证明环境已经正常,只不过在项目启动的时候,出现了错误,也就是说是项目代码的问题。
方案:查看日志,看项目文件是否齐全。
如果你不知道如何打开日志,请看另一篇文章的这一节:https://www.cnblogs.com/laozhang-is-phi/p/9565227.html#autoid-5-5-0
下边这个错误,就是因为分离的原因,导致 Service.dll 和 Repository.dll ,或者 swagger 的xml 没有拷贝到发布文件夹下,从而导致项目没有启动起来。
8、总结
经过上边多个错误分析,如果我们第一次再服务器中部署,只需要安装 服务器托管 Windows-hosting 即可:
https://dotnet.microsoft.com/download/dotnet-core/3.0
三、Vue 错误
1、跨域失败
这都是很简单的错误,根据上边的动图,咱们也能看出来,关于跨域有以下几个方法:
1、IIS 部署,一定要在后端 NetCore 项目,进行 CORS 跨域;
2、除非你是在 IIS 中的同一个站点配置前后端两个项目;
3、如果是 nginx+kestrel 的话,记得在 nginx 中配置跨域代理;
4、其他方案,略;
2、页面刷新 404
为了这个错误,我上边的第一个动图,还特地的故意做了这个错误,就是 history 和 hash 的情况,当然也是有两个方案:
如果是IIS部署
1、如果你是 IIS 部署,就使用 hash 模式;
2、如果用IIS,也想用 history 模式,可以配置 URL重写:https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90
如果是Nginx部署:
1、不过如果用 nginx 的话,可以利用 404 页面的机制,将 index.html 页面 copy 一份,重命名成 404.html 即可;
2、如果不想添加一个 404 文件的话 ,就直接修改下 nginx 的配置文件(推荐)
官方解释:https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90
3、IIS 无法导入组件
在 Blog.Admin 项目中,都尝试下这两个导入方式。
如果还不行,就直接修改下导入组件的地方吧(感谢群友@听风者小伙伴提出的方案),不要说不知道这个代码在哪里修改:
四、Github & Gitee
https://github.com/anjoy8/Blog.Core
https://gitee.com/laozhangIsPhi/Blog.Core