Linux-Docker部署.netCore程序

2023-05-16

说明

.netcore 程序涉及mysql、redis。后续还需要通过nginx反向代理与域名绑定在一起,所以我们需要先部署mysql、redis、nginx,再进行.netcore程序部署

我们先走一遍docker流程,后续再用docker-compose将这些服务"一网打尽"

环境:linux(centOS),未安装docker的可以参考Install Docker Engine on CentOS | Docker Documentation

本文需要有一定docker基础,如镜像、容器的操作等等

docker 安装 mysql

拉取镜像

docker hub mysql 镜像 Tags | Docker Hub

创建本地挂载文件
创建并启动容器
  • -itd:指定后台交互运行
  • --name:指定容器名称
  • -p:端口映射,前者机器端口,后者容器端口,mysql默认3306
  • -v:挂载文件,主要是将容器存储的文件或读取的配置映射到本地,容器挂了或删除了,数据不受影响(重新启动新容器再次挂在即可)
  • --restart:容器退出时应用的重启策略(默认否),--restart=always 容器退出时会重启容器
  • -e:设置环境变量,-e MYSQL_ROOT_PASSWORD=123456 设置mysql root用户的初始密码
查看容器是否启动成功

image-20230512145556683

查看mysql是否可用

image-20230512150040977

docker 安装 redis

拉取镜像

docker hub redis 镜像 Tags | Docker Hub

创建本地挂载文件
创建并启动容器
  • -d:指定后台运行
  • --name:指定容器名称
  • -p:端口映射,前者机器端口,后者容器端口,mysql默认6379
  • -v:挂载文件,主要是将容器存储的文件或读取的配置映射到本地,容器挂了或删除了,数据不受影响(重新启动新容器再次挂在即可)
  • --appendonly yes 开启redis持久化
查看容器是否启动成功

image-20230512151929155

查看redis是否可用

image-20230512152316011

docker 安装 nginx

拉取镜像

docker hub nginx 镜像 Tags | Docker Hub

创建本地挂载文件
默认启动nginx

启动后获取容器内部默认配置文件到宿主机

停止容器并将其删除
创建并启动容器
  • -d:指定后台运行
  • --name:指定容器名称
  • -p:端口映射,前者机器端口,后者容器端口,nginx默认80
  • -v:挂载文件,主要是将容器存储的文件或读取的配置映射到本地,容器挂了或删除了,数据不受影响(重新启动新容器再次挂在即可)
  • --restart:容器退出时应用的重启策略(默认否),--restart=always 容器退出时会重启容器
查看容器是否启动成功

image-20230512153343272

查看nginx是否可用

image-20230512153843014

docker 部署 .net core程序

项目生成Dockerfile

主项目右键—>添加—>docker支持 —>选择平台(linux),然后就会在该项目下生成Dockerfile文件。Dockerfile里面的内容我们先不用管,直接将该文件移动到解决方案目录即可,这样做可以避免Dockerfile构建的时候找不到项目依赖的问题。

image-20230515104611132

Dockerfile说明

正常来说,VS自动生成的Dockerfile不需要做太大变动,我们只需要关注暴露端口和工作目录即可

更多解释可以参考[Docker] .NET Core 的 Dockerfile 指令詳解 | K. C. - 點部落 (dotblogs.com.tw)

image-20230515110010102

docker打包发布程序(手动)

切换到解决方案目录(含有Dockerfile的目录),打开终端,执行build命令

image-20230515110940310

保存镜像到本地

image-20230515113036870

将文件上传至服务器,加载镜像

image-20230515113639447

docker打包发布程序说明

打包发布有多种,大家可以自行搜索,整体步骤大差不差,怎么方便怎么来

  1. 本地构建(build)—>打包镜像(save)—>上传镜像到服务器—>读取镜像(load)
  2. 本地构建(build)—>推送镜像仓库(push)—>服务器从镜像仓库拉取镜像(pull)——常用
  3. 本地代码上传代码到git远程仓库(git push)—>服务器从git远程仓库拉取代码(git pull)—>服务器构建(build)——慎用
创建并启动容器
  • -d:指定后台运行
  • --name:指定容器名称
  • -p:端口映射,前者机器端口,后者容器端口,nginx默认80
  • -v:挂载文件,主要是将容器存储的文件或读取的配置映射到本地,容器挂了或删除了,数据不受影响(重新启动新容器再次挂在即可)
  • --restart:容器退出时应用的重启策略(默认否),--restart=always 容器退出时会重启容器

如果需要将资源文件或配置文件放到宿主机上,我们可以使用-v挂载磁盘,操作如下:

值得一提,拷贝容器的资源文件和配置文件到宿主机仅需要执行一次,不需要每次发布都执行一次,以免覆盖掉文件。后续发布更新时我们只需要执行带-v的docker run 命令即可

还要注意的是,如果你的程序依赖别的程序,而别的程序又没启动或者配置,那么你的程序就会报错,程序报错容器就会停止运行,此时可以使用logs命令查看日志,以寻求解决方法。

到这里我们.net core 程序、mysql服务、redis服务、nginx都已经装好了

image-20230515115755506

时区问题

大陆玩家要注意了,如果你的宿主机时区是Asia/Shanghai ,那就要将.net core程序的容器时区和宿主机的时区保持一致。容器内部默认是utc时区,也就是说容器内部的时间和宿主机的时间(东八区)差了8小时。容器获取时间的相关程序都会有差错,所以我们需要将.net core程序的容器时区和宿主机的时区保持一致。

注意了,-v /etc/localtime:/etc/localtime 是可以将容器时区和宿主机保持一致,但是程序获取的时间还是utc时间。

image-20230515120719380

我们应该如此:

效果如图,宿主机时间、容器时间、程序获取时间基本保持一致

image-20230515121257621

当然,时区问题也可以直接Dockerfile文件的final阶段执行以下命令,这样就不需要每次发布都手动同步时区了

nginx反向代理

通过上面的一通操作,我们已经成功启动.net core程序,并且分配端口为5000。我们需要访问http://127.0.0.1:5000才能正常访问,那怎样做将端口去掉(将端口设为80,访问时端口80可忽略)也能正常访问.net core程序呢?nginx就派上用场了

因为我们上面已经将nginx配置文件挂载到宿主机磁盘,我们直接改宿主机的nginx配置文件即可

image-20230516115119951

nginx配置文件修改内容

image-20230516114923894

docker-compose 一键操作管理服务

涉及到多个服务操作,如果每次都需要单独执行docker run来启动,那就太麻烦了。我们可以使用docker-compose来管理我们的服务

docker-compose安装卸载

安装

卸载

编写docker-compose.yaml

根据上面的docker run 命令,我们可以很快编写docker-compose文件,起始docker-compose就是根据docker命令编写的,做的都是同一件事

注意做注释或者编写时的时候不要用Tab键,可能会出现错误

docker-compose 常用说明
  • version——版本,默认1

  • services——服务集合

    • container_name——string,容器名称

    • labels——string,设置服务标签,metadata

    • image——string,指定需要拉取或使用的镜像,若没有build,则以该镜像运行容器。可以是镜像ID或者是镜像:tag

    • build——string/object,构建目录(含Dockerfile的目录)当前目录则用.表示即可。当build和image字段都存在时,使用image指定的镜像名和tag作为build后镜像的name和tag

      • context:——string,指定上下文所在的目录,当前目录则用.表示即可。可以是git仓库的url也可以是绝对/相对路径
      • dockerfile:——string,指定Dockerfile文件名称
      • args——object,执行build参数
    • volumes——array,挂载磁盘(不存在时,自动创建,建议自行手动创建),也可以挂载卷标(在与services同级的volumes定义)

    • ports——array,暴露端口,映射端口。"宿主机端口:容器端口"

    • environment:object,指定环境变量

    • command:array, 执行指定命令

    • restart——string,默认no。always—失败后总是重启,on-failure—错误码为 on-failure 时才重启,unless-stopped—手动停止后不重启,no—失败不重启

    • depends_on——array,依赖服务,先启动依赖服务在启动本服务。这里写的是服务名称,不是容器名称

    • network——array,为容器指定网络。默认default

    • shm_size——number/string,'2gb'或者10000000(字节)。设置容器内/dev/shm目录的大小,/dev/shm目录非常重要,此目录并不在硬盘上,而是在内存中,默认大小为内存的一半大小,存入其中的文件不会被清空,容器内划分此目录可以一定程度上指定容器的性能

  • volumes——卷标,供services内的服务使用,更多请参考:docker-compose-volumes的说明 - 简书 (jianshu.com)

  • networks——网络配置,供services内的服务使用。不填时,默认services内的所有服务使用同一个网络,即可以在服务1中访问服务2的端口,更多请参考:docker-compose的网络networks的使用技巧 - 知乎 (zhihu.com)

docker-compose 常用命令
启动所有服务

docker-compose.yaml文件编写完后,我们可以使用up指令启动docker-compose.yaml里面列出的所有服务

停止所有服务

down指令将停止运行的容器,并且会删除已停止的容器以及已创建的所有网络。添加-v标记删除所有卷

查看镜像

列出 Compose 文件中包含的镜像。

image-20230515174550956

列出项目中所有容器
暂停服务

unpause可以解除暂停

image-20230515174820928

不暂停服务

image-20230515175033321

停止服务

注意stop指令只能指定服务名称,不知道为什么。停止的服务可以用start指令启动

image-20230515175735112

启动服务(单个)

image-20230515175950350

重启服务(单个)

t, --timeout TIMEOUT 指定重启前停止容器的超时(默认为 10 秒)

验证compose文件正确性