菜的像徐坤
排名
6
文章
6
粉丝
16
评论
8
{{item.articleTitle}}
{{item.blogName}} : {{item.content}}
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2024TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

linux +docker +nginx +mssql 部署NetCore Mvc 多站点项目

5378人阅读 2022/11/11 18:13 总访问:876754 评论:1 收藏:2 手机
分类: Docker

前言

通过一个星期的踩坑,终于。终于。终于。将项目部署成功!
接下来分享一些实际项目中遇到的坑。也算是自己的工作积累吧。
注意:Linux 中路径是严格区分大小写的哦,多检查一下项目的文件路径
先提前在Linux 服务器上先把net core 的依赖,docker 和 nginx 都装好

项目

工作需求是将一个多站点项目部署到docker  

单站点发布倒是简单,多站点这可咋整?DockerFile放在哪儿?应该一个站点一个站点发还是一起发?静态文件和配置文件又该怎么处理?等等。。。。。。。
接下来开始第一步
先测试站点是否能够在本地跑起来(所有站点,如果有站点跑不起来现在本地检查,保证每个站点能够单独自依赖运行)
最重要的一点:项目中绝对不能出现绝对地址,例如   D:/微信文件/WeChat Files/All Users  只能用相对路径  ../WeChat Files/All Users 


所有站点都能运行了,在本地运行一下,发现还是不行,因为站点与站点之间存在互相依赖关系,所以打开地址之后发现是404
后面检查发现,项目中的请求都是以  站点/控制器/页面   这种方式请求的,因为站点与站点之间存在互相依赖关系,站点信息已经明确了,所以在请求中多加了一个站点所以请求地址不对了



该怎么解决呢?改项目中的代码的话,工作量会不会太大了,而且你也不知道那些东西改了会不会出一些不可预料的错误
来说说解决办法吧
中间件中将 pattern 将路由处理一下,这样再有请求进来,所有的请求地址将会被路由处理:例如 :/BasicApplication/Retrieval/index  将会变成  /Retrieval/index

        /// <summary>
        /// 添加Endpoint并Area路由支持
        /// </summary>
        public static IEndpointRouteBuilder MapControllersWithAreaRoute(this IEndpointRouteBuilder endpoints, bool area = true)
        {
            if (area)
            {
                endpoints.MapControllerRoute(
                    name: "area-route",
                    //areaName:"area",
                    pattern: "{site:}/{area:exists}/{controller=Home}/{action=Index}/{id?}"
                    );

                endpoints.MapControllerRoute(
                   name: "viewName",
                   pattern: "{site:}/{area:exists}/{controller}/{*viewName}",
                   defaults: new { action = "DisplayAnyView" }
                );
            }
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{site:}/{controller=Home}/{action=Index}/{id?}"
                );
            endpoints.MapControllerRoute(
                name: "viewName",
                pattern: "{site:}/{controller}/{*viewName}",
                defaults: new { action = "DisplayAnyView" }
                );
            return endpoints;
        }

本地的地址的问题解决了,接下来再启动就发现问题解决啦
接下来把发布文件拷贝到 linux 服务器上(文件中有站点发布文件,静态文件和配置文件)




拷贝过去之后在用命令运行一下单站点(window上能跑,linux上一般都能跑,注意多检查静态文件的路径)

站点没问题之后就可以将文件打包成镜像了,这里是打包到docker

应该一个站点一个站点发还是一起发?这肯定是要一个站点一个站点的发的。

需要在每个站点下新增DockerFile(我这里使用的是centOS 8 数据库链接上需要处理一下协议问题)为了防止出现这个错误  provider: TCP Provider, error: 35 - An internal exception was caught

在.NET Core/.NET 5的容器镜像中的OpenSSL的最低协议版本要求为TLSv1.2,而我们的MS SQL Server所用的版本较低,不支持TLSv1.2只支持TLSv1

可参考 https://blog.csdn.net/farway000/article/details/124441124 或者在 dockerfile中 加上 这一句  RUN sed -i 's/TLSv1.2/TLSv1/g' /etc/ssl/openssl.cnf  

我先例出一个站点的示例,其他站点类似
dockerfile 示例

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base

WORKDIR /app/Basicapplication

EXPOSE 80

COPY  . .
 
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN sed -i 's/TLSv1.2/TLSv1/g' /etc/ssl/openssl.cnf

ENV ASPNETCORE_URLS=http://+:80

ENTRYPOINT ["dotnet", "BasicApplication.dll","--server.urls","http://*:80"]

每个站点一个dockerfile ,因为要把每个站点部署在不同的容器中

建议不要将多余文件也build到镜像,包括静态文件,配置文件。(建议建立一个镜像,检查一下是否创建成功,避免重复创建后面花时间一个一个删)

创建镜像:docker build -f /home/zhangweifeng/公共/linux/BasicApplication/Dockerfile -t basic:v1 .      (镜像image 不能用大写名称命名否则会报错)

将所有镜像创建好(再次确认你的镜像是能运行的,不然放进容器会报错,而且容器也起不来)


镜像建立好之后,还不能忘了还有静态文件和配置文件需要挂载到容器里。不然容器启动时会提示文件路径找不到。

怎么挂载静态文件呢?可参考 https://www.tnblog.net/aojiancc2/article/details/7723 

下边直接上代码:

docker run 
-v /home/zhangweifeng/公共/linux/WebResource:/app/WebResource/ 
-v /home/zhangweifeng/公共/linux/ExcelTemplate:/app/ExcelTemplate/ 
-v /home/zhangweifeng/公共/linux/TempFolder:/app/TempFolder/ 
-v /home/zhangweifeng/公共/linux/share:/app/share/ 
-v /home/zhangweifeng/公共/linux/NKConfig.json:/app/NKConfig.json 
-v /home/zhangweifeng/公共/linux/nlog.config:/app/nlog.config 
-v /home/zhangweifeng/公共/linux/web.config:/app/web.config 
-v /home/zhangweifeng/公共/linux/WW_verify_k2C7T5PiccuF4fiZ.txt:/app/WW_verify_k2C7T5PiccuF4fiZ.txt 
-p 9001:80 basic:v1

-p 9001:80 代表的就是    将容器内80端口 映射到宿主机的9001 端口。访问本机9001端口就等于访问到容器内的80端口
每个容器指定的端口不能重复,这里我有5个站点,配了5个端口分别为 9001,9002,9003,9004,9005,9006(后边需要做nginx代理的)
目录挂载上之后,运行还是行的话,还得检查一下容器内的路径映射的对不对了,容器内以项目文件为准,静态文件该放上级放上级,该放同级放同级。


把每个容器都跑起来

跑起来之后发现,每个项目都是独立的,他们之间的互相引用应该怎么处理呢。
这时候就需要用到 nginx 了


查看nginx所在目录

which nginx


启动 nginx

转到nginx所在目录  ->  ./nginx


修改nginx 配置文件


要编辑nginx文件得用命令,因为它是只读的

新增如下端口配置

输入 i 进入编辑模式
按住 shift + : 退出编辑模式
输入 wq! 保存并退出


每个不同的请求标识转发到不同的端口,这个就需要根据自己的项目配置了。nginx配置比较简单,保存完成之后

重新加载nginx配置文件

nginx -s reload


我这里是用8011 端口代理的,在服务器访问发现没问题,但是我在自己电脑上发现访问不到8011,但是访问 9001 又是可以的
这也是一个小坑,因为服务器没有开放8011 端口,所以需要将8011端口开放,才能在自己电脑上访问到


开放端口命令:/sbin/iptables -I INPUT -p tcp --dport 8011 -j ACCEPT


查看防火墙所有开放的端口

firewall-cmd --zone=public --list-ports


开放端口

firewall-cmd --zone=public --add-port=8092/tcp --permanent

关闭端口

firewall-cmd --zone=public --remove-port=5672/tcp --permanent


配置立即生效

firewall-cmd --reload

 


评价