背景知识
启动Gitlab Runner时,使用Gitlab提供的官方镜像gitlab/gitlab-runner:latest即可。
Runner以容器的方式启动以后,根据前文我们注册到Gitlab服务器,然后就可以等着执行“流水线”里面的“作业”了。
执行“作业”是要启动另外的容器的,在这个容器里面才能运行dotnet build、dotnet pack甚至docker build之类的命令的。“作业”结束,这个容器会自动销毁。
本文要制作的镜像,是给这一步的临时容器用的。
准备一个空白的制作镜像的目录
这个目录下,将会有3个文件。1个是Docker打包必须的Dockerfile文件,没有扩展名。另外两个是我们引入了微软的集中定义版本号的技术,所依赖的,我们放在镜像里,能让我们编写.gitlab-ci.yml的时候更加规范和便捷。
1、Dockerfile
from ubuntu:20.04
MAINTAINER zhongfang@qq.com
RUN apt update && apt install -y libcurl4
RUN apt install wget -y
RUN apt install apt-utils -y
RUN ln -s /lib/x86_64-linux-gnu/libdl-2.24.so /lib/x86_64-linux-gnu/libdl.so
RUN wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
RUN dpkg -i packages-microsoft-prod.deb
RUN apt-get update
RUN apt-get install -y apt-transport-https
RUN apt-get update
RUN apt install net-tools -y
RUN apt install bind9-utils -y
RUN apt install vim -y
RUN apt install iputils-ping -y
RUN apt-get install -y dotnet-sdk-5.0
RUN apt-get install -y dotnet-sdk-6.0
RUN apt-get install -y dotnet-sdk-7.0
RUN apt-get install -y dotnet-sdk-8.0
RUN apt-get install docker.io -y
RUN mkdir /root/.ssh
# SSH私用私钥登入远程服务器时,本地.ssh文件夹的权限必须正确的限制
RUN chmod -R 700 /root/.ssh
RUN mkdir /home/public
COPY download-directory-builds-props.sh /home/public
COPY ssh-to-http-server-for-update-version-number.sh /home/public
COPY ssh-to-app-server-for-docker-run.sh /home/public
RUN chmod +x /home/public/*.sh
#现在用docker build会收到警告,要求使用docker buildx
#下边语句来源于https://github.com/docker/buildx?tab=readme-ov-file#dockerfile
COPY --from=docker/buildx-bin /buildx /usr/libexec/docker/cli-plugins/docker-buildx
2、download-directory-builds-props.sh
脚本的参数
- http网址根目录,比如http://dev.amihome.cn
脚本的作用
- 删除当前目录及其子目录下的 Directory.*.props文件
- 删除当前目录下的urls.txt文件
- 下载根目录下的urls.txt文件,这个文件里面是Directory.Build.props中Import的子文件
- 下载根目录下的Directory.Build.props到当前目录
- 下载urls.txt里每一行的文件到当前目录,wget自动根据网址创建子目录
说明
- wget的-nH开关,是不要创建以网站服务器为名的目录
- urls.txt如果是Windows的记事本创建的,换行符会被从“\r\n”替换成“\r”
#!/bin/bash
echo off
rm -vf Directory.*.props
# 文件名
file="urls.txt"
rm -vf $file
echo "共享版本号的http服务器是" $1
urlsFile="$1/$file"
echo "下载urlx.txt"
echo $urlsFile
wget $1$urlsFile --content-disposition
# 检查文件是否存在
if [ ! -f $file ]; then
echo "$file 不存在"
exit 1
fi
# 循环读取文件内容
while IFS= read -r line; do
# echo "$line"
# WIndows以“\r\n”作为换行符,Shell里只有最后的“\n”被识别为换行符
# 所以程序员在Windows下用“记事本”编辑的urls.txt文件,需要做下面的处理
new_content=$(echo "$line" | tr -d '\r')
wget -nv -x -nH $new_content --content-disposition
done < "$file"
# 可以清理nuget的缓存,目前看起来不需要
# 不清理可以节省打包的时间
# dotnet nuget locals plugins-cache --clear
3、ssh-to-http-server-for-update-version-number.sh
参数说明
- 登入远程服务器的Linux账户名称;
- 分发版本号的http服务器名称或IP地址;
- 网站根目录的文件夹名称。为了安全,网站都是放在/www/wwwroot目录下,所以不用传入“/www/wwwroot/”;
- 文件名。这个文件名称,就是被Directory.Build.props里Import的那个文件的名称。约定了必须放在网站根目录的“version-numbers”目录下;
- 新的版本号。
#!/bin/bash
echo "登入远程服务器的linux账户名称" S1
echo "分发版本号的http服务器名称或IP" $2
echo "网站根目录的文件夹名称" $3
echo "文件名:" $4
echo "新的版本号" $5
# 这个文件夹里有用户的私钥,配合传进来的用户名$1,就能免密码登入到远程服务器了
# /deploy/ssh 这个目录,是在Runner的config.toml文件里面挂载的
cp /deploy/ssh/* /root/.ssh
ssh $1@${2} <<EOF
cd /www/wwwroot/$3/version-numbers
sed -i "s/\([0-9\.]\{2,20\}\)/$5/g" $4
4、ssh-to-app-server-for-docker-run.sh
SSH登入应用服务器,执行docker run
#!/bin/bash
echo "docker容器实例名称:" $1
echo "目标服务器对外端口号" $2
echo "docker容器开放端口号" $3
echo "docker镜像URL" $4
echo "容器AspNetCore的环境【ASPNETCORE_ENVIRONMENT】" $5
echo "Docker服务器DNS名称" $6
echo "登入Docker服务器的用户名称" $7
echo "登入Docker服务器的密码" $8
echo "SSH自动登入目标服务器使用的用户名" $9
echo "SSH自动登入的目标服务器" ${10}
echo "在服务器上执行的命令是"
echo "docker run -d --privileged=true --restart=always -d --name "$1" -v /mnt/data/yee-change:/var/config -e ASPNETCORE_ENVIRONMENT="$5" -p "$2":"$3 $4ssh $9@${10} <<EOF
EOF
# cd;bash ~/docker/gitlab/runner/deploy.sh $1 $2 $3 $4 $5 $6 $7 $8
# 下边的命令,是在远程服务器上执行的
conName=$1
eonPort=$2
conPort=$3
images=$4
# 下边的命令,是在远程服务器上,停止和删除容器及image
count=`docker ps -a |grep "$conName"|wc -l `
if [ $count -eq 0 ];then
echo "$conName container is not exit"
else
id=$(docker ps -a |grep "$conName" |awk '{print $1}')
for i in $id
do
docker stop $i
docker rm $i
done
fi
docker rmi $images
docker login -u $7 -p $8 $6
docker run --restart=always -d --name $conName -v /mnt/config:/var/config -e ASPNETCORE_ENVIRONMENT=$5 -p $eonPort:$conPort $images
构建和推送镜像到仓库
做好上述准备工作,我们的工作目录下有4个文件:
root@dev-server:/data/images/gitlab/docker-linux-dotnet8.0# ls -al
total 24
drwxr-xr-x 2 root root 4096 Feb 28 11:47 .
drwxr-xr-x 5 root root 4096 Feb 28 10:08 ..
-rw-r--r-- 1 root root 1253 Feb 28 07:22 Dockerfile
-rwxr-xr-x 1 root root 825 Feb 28 00:53 download-directory-builds-props.sh
-rw-r--r-- 1 root root 1337 Feb 28 10:57 ssh-to-app-server-docker-run.sh
-rw-r--r-- 1 root root 524 Feb 27 13:55 update-remote-version-number.sh
docker build
docker build -t docker.amihome.cn/amihome/gitlab/docker-linux-dotnet8.0:latest .
docker push
docker push docker.amihome.cn/amihome/gitlab/docker-linux-dotnet8.0:latest
如果没有登入docker仓库,必须先执行docker login username
黑夜里不停折腾的代码行者。