docker容器下的asp.net core项目发布运维

对近期项目的发布运维进行总结,项目前后端分离,后端利用docker部署,运维目标为一键发布运行项目最新版本。

一、服务器环境

服务器版本

CentOS Linux release 7.6.1810 (Core)。

用户

app

测试项目

后端cms,前端cms-static

二、相关目录

项目运行目录:

/data/www/html/cms/

/data/www/html/cms-static/

项目附件目录,可软链接至NFS:

/data/file/cms/

项目日志目录:

/data/www/html/cms_logs/

运维目录:

/shell/

代码仓库目录:

/shell/code_review/cms/

/shell/code_review/cms-static/

运维主管目录,

下包含代码仓库、发布文件仓库、发布打包脚本等:

/shell/code_review/admin/

配置目录:

/config/cms/

脚本目录:

/shell/release/

以上目录权限均设置为:

drwxr-xr-x app app

三、发布脚本

后端发布脚本:

/shell/release/11.release.cms.sh

 1 #!/bin/bash
 2 
 3 [ `whoami` != app ] && echo "Please use user 'app', su app" && exit
 4 
 5 SOURCE_DIR=/shell/code_review/cms/
 6 RELEASE_DIR_TMP=/tmp/dev/cms/
 7 RELEASE_DIR=/data/www/html/cms/
 8 
 9 [ -d $RELEASE_DIR_TMP ] || mkdir -p $RELEASE_DIR_TMP
10 
11 cd $SOURCE_DIR  ; git checkout . ; git pull
12 cd src/Cms.Web.Host
13 dotnet publish -c Release -o $RELEASE_DIR_TMP
14 
15 if [ $? != 0 ] ; then
16   echo "Build Failure"
17   exit
18 else
19   echo "Build Success"
20 fi
21 
22 docker-compose -f /shell/compose/cms/compose-cms.yml down
23 
24 /usr/bin/rsync -togplar --delete-after --progress \
25 --exclude=Thumbs.db \
26 --exclude='.svn/'  \
27 --exclude='.git/'  \
28 --exclude='\.*'  \
29 --exclude='Logs/'  \
30 --exclude='appsettings.json'  \
31 $RELEASE_DIR_TMP    $RELEASE_DIR \
32 | sed 's/\r//g' \
33 | sed '/to-check/d'  \
34 | sed '/sending incremental file list/d'  \
35 | sed '/building file list/d' \
36 | sed '/ to consider/d' \
37 | sed '/bytes\/sec/d' \
38 | sed '/total size is /d' \
39 | sed '/\/$/d' \
40 | sed '/^$/d' \
41 >> /shell/release/logs/release.dev.cms.rsync.`date +%F`.log
42 
43 \cp -f /config/cms/cms/appsettings.json  $RELEASE_DIR
44 
45 docker-compose -f /shell/compose/cms/compose-cms.yml up -d

docker-compose配置文件:

/shell/compose/cms/compose-cms.yml

 1 version: "2.2"
 2 services:
 3 #dotnet
 4   cms:
 5     user: app
 6     environment:
 7     -  LANG=en_US.UTF-8
 8     -  ASPNETCORE_URLS='http://0.0.0.0:8010'
 9     restart: always
10     network_mode: host
11     image: dotnet:v3.1.1
12     ports:
13       - "127.0.0.1:8010:8010"
14       #- "0.0.0.0:8010:8010"
15     volumes:
16       - "/data/:/data/"
17       - "/shell/:/shell/"
18       - "/config:/config"
19       - "/etc/localtime:/etc/localtime"
20 #    mem_limit: 1024m
21 #    extra_hosts:
22 #    - "mysqlserverip:172.16.0.48"
23     container_name: cms
24     entrypoint: /shell/release/docker.start.cms.sh

docker入口脚本文件:

/shell/release/docker.start.cms.sh

1 #!/bin/bash
2 
3 cd /data/www/html/cms
4 export ASPNETCORE_URLS='http://0.0.0.0:8010'
5 dotnet Cms.Web.Host.dll >> /data/www/html/cms_logs/Cms.`date +%F`.log#这里为项目启动日志,项目运行日志配置即log4net配置。

前端发布脚本:

/shell/release/13.release.cms-static.sh

 1 #!/bin/bash
 2 [ `whoami` != app ] && echo "Please use user 'app', su app" && exit
 3 
 4 SOURCE_DIR=/shell/code_review/cms-static/
 5 RELEASE_DIR_TMP=/shell/code_review/cms-static/dist/
 6 RELEASE_DIR=/data/www/html/cms-static/
 7 
 8 [ -d $RELEASE_DIR_TMP ] || mkdir -p $RELEASE_DIR_TMP
 9 
10 cd $SOURCE_DIR
11 git checkout .
12 git pull
13 npm install
14 npm run build:prod
15 
16 if [ $? != 0 ] ; then 
17   echo "Build Failure"
18   exit
19 else
20   echo "Build Success"
21 fi
22 
23 /usr/bin/rsync -togplarc --delete-after --progress \
24 --exclude=Thumbs.db \
25 --exclude='.svn/'  \
26 --exclude='.git/'  \
27 --exclude='\.*'  \
28 $RELEASE_DIR_TMP   $RELEASE_DIR  \
29 | sed 's/\r//g' \
30 | sed '/to-check/d'  \
31 | sed '/sending incremental file list/d'  \
32 | sed '/building file list/d' \
33 | sed '/ to consider/d' \
34 | sed '/bytes\/sec/d' \
35 | sed '/total size is /d' \
36 | sed '/\/$/d' \
37 | sed '/^$/d' \
38 >> /shell/release/logs/release.dev.cms-static.rsync.`date +%F`.log

四、拓展补充

1,项目配置文件

在上面的发布脚本中,有一步操作为 cp -f /config/cms/cms/appsettings.json $RELEASE_DIR ,即在程序发布后,复制最新的配置文件到发布目录。配置文件库与代码仓库分离,采用svn或git工具单独管理。

2,hosts文件

在配置文件中出现多次变量,存储于/etc/hosts文件。

172.16.0.45     mysqlserverip
172.16.0.46     redisserverip
172.16.0.47     appserverip
172.16.0.48     qzserverip
172.16.0.100    svn.mytest.com
172.16.0.101    gitlab.mytest.com
172.16.0.102    ldap.mytest.com
172.16.0.103    crowd.mytest.com

3,git配置

发布脚本中,有进入代码仓库目录拉取的动作,需要提前配置好app用户下的git免密。

1 echo "https://release-who-r-u:Not***@gitlab.mytest.com" > ~/.git-credentials 
2 git config --global credential.helper store #会在用户根目录生成文件.gitconfig
3 cat ~/.git-credentials
4 cat ~/.gitconfig

4,nginx前置

互联网访问项目站点均经由nginx前置转发到app服务器相关端口,本文重点在于说明一键发布运维的建立,前置转发配置及前置相关性能分析优化等部分不做赘述。

5,传统发布脚本

前面介绍了利用docker容器进行发布,这里顺带再总结下传统的发布方式。

/shell/release/11.release.cms.sh

 1 #!/bin/bash
 2 
 3 SOURCE_DIR=/shell/code_review/cms/
 4 RELEASE_DIR_TMP=/tmp/dev/cms/
 5 RELEASE_DIR=/data/www/html/cms/
 6 
 7 [ -d $RELEASE_DIR_TMP ] || mkdir -p $RELEASE_DIR_TMP
 8 
 9 cd $SOURCE_DIR   ; git checkout . ; git pull ; cd ../
10 
11 cd cms/src/Cms.Web.Host/
12 dotnet publish -c Release -o $RELEASE_DIR_TMP
13 
14 if [ $? != 0 ] ; then 
15   echo "Build Failure"
16   exit
17 else
18   echo "Build Success"
19 fi
20 
21 /bin/bash /shell/release/21.restart.cms.sh stop
22 
23 /usr/bin/rsync -togplar --delete-after --progress \
24 --exclude=Thumbs.db \
25 --exclude='.svn/'  \
26 --exclude='.git/'  \
27 --exclude='\.*'  \
28 --exclude='Logs/'  \
29 --exclude='appsettings.json'  \
30 $RELEASE_DIR_TMP    $RELEASE_DIR \
31 | sed 's/\r//g' \
32 | sed '/to-check/d'  \
33 | sed '/sending incremental file list/d'  \
34 | sed '/building file list/d' \
35 | sed '/ to consider/d' \
36 | sed '/bytes\/sec/d' \
37 | sed '/total size is /d' \
38 | sed '/\/$/d' \
39 | sed '/^$/d' \
40 >> /shell/release/logs/release.dev.cms.rsync.`date +%F`.log
41 
42 /bin/bash /shell/release/21.restart.cms.sh start

/shell/release/21.restart.cms.sh

 1 #!/bin/bash
 2 
 3 [ `whoami` != app ] && echo "Please use user 'app', su app" && exit
 4 source /etc/profile
 5 
 6 case "$1" in
 7     stop)
 8 # stop
 9 pkill -f Cms.Web.Host.dll
10 sleep 2
11 [ `ps auxf |grep Cms.Web.Host.dll | grep -v grep | wc -l ` -gt 0 ] && pkill -9 -f Cms.Web.Host.dll
12 ;;
13 
14 start)
15 # start
16 cd /data/www/html/cms
17 export ASPNETCORE_URLS='http://0.0.0.0:8010'
18 \cp /config/cms/cms/appsettings.json  /data/www/html/cms/
19 
20 nohup dotnet Cms.Web.Host.dll >> /tmp/nohup.cms.`date +%F`.log  2>&1 &
21 sleep 1
22 ps -ef|grep Cms.Web.Host.dll
23 ;;
24 
25 restart)
26     /bin/bash /shell/release/21.restart.cms.sh stop && /bin/bash /shell/release/21.restart.cms.sh start
27 ;;
28 *)
29     /bin/bash /shell/release/21.restart.cms.sh stop && /bin/bash /shell/release/21.restart.cms.sh start
30 ;;
31 esac
32 exit 0

6,一键打包

项目运维中除了直接发布运行的情形,还有一键发布打包上传最新版本程序文件的需求,可通过以下脚本实现,这里举例是发布后直接上传到了svn版本库。

/shell/code_review/admin/12.release.cms.sit.sh

 1 #!/bin/bash
 2 
 3 SOURCE_DIR=/shell/code_review/admin/my-repos/sit/
 4 RELEASE_DIR_TMP=/tmp/sit/cms/
 5 RELEASE_DIR_SVN=/shell/code_review/admin/updates/sit/code-release/cms/
 6 
 7 [ -d $RELEASE_DIR_TMP ] || mkdir -p $RELEASE_DIR_TMP
 8 
 9 cd $SOURCE_DIR
10 cd cms            ; git checkout . ; git pull ; cd ../
11 
12 cd cms/src/Cms.Web.Host/
13 dotnet publish -c Release -o $RELEASE_DIR_TMP
14 
15 if [ $? != 0 ] ; then 
16   echo "Build Failure"
17   exit
18 else
19   echo "Build Success"
20 fi
21 
22 /usr/bin/rsync -togplar --delete-after --progress \
23 --exclude=Thumbs.db \
24 --exclude='.svn/'  \
25 --exclude='.git/'  \
26 --exclude='\.*'  \
27 --exclude='Logs/'  \
28 --exclude='appsettings.json'  \
29 $RELEASE_DIR_TMP    $RELEASE_DIR_SVN \
30 | sed 's/\r//g' \
31 | sed '/to-check/d'  \
32 | sed '/sending incremental file list/d'  \
33 | sed '/building file list/d' \
34 | sed '/ to consider/d' \
35 | sed '/bytes\/sec/d' \
36 | sed '/total size is /d' \
37 | sed '/\/$/d' \
38 | sed '/^$/d' \
39 >> /shell/release/logs/release.sit.cms.rsync.`date +%F`.log
40 
41 cd $RELEASE_DIR_SVN
42 svn st | grep "? \+" && svn add `svn st | grep "? \+" | sed "s/? \+//" | grep -v " "`
43 svn st | grep "! \+" && svn delete `svn st | grep "! \+" | sed "s/! \+//" | grep -v " "`
44 svn st | grep "? \+" && svn add "`svn st | grep "? \+" | sed "s/? \+//" `"
45 svn st | grep "! \+" && svn delete "`svn st | grep "! \+" | sed "s/! \+//"`"
46 svn st && svn ci -m 'auto commit by script'