在Linux中如何在没有latest标签的情况下,如何获取最新的docker镜像中最新的tag,并自动部署的shell脚本
在之前的工作中,我经常需要对在华为云上部署项目,同时每次部署的时候都要自己去仓库拿最新的tag,然后使用docker进行一系列操作,多弄几次之后感觉很麻烦。于是想着弄一个自动部署docker的脚本,最开始的思路是使用docker search 来获取images,但是我们的镜像在华为云的私有仓库中,根本搜索不到。于是只能去看华为云的api来获取最新的tag了,而从华为云上获取tag需要先获取授权,拿到相应的token然后在用这个token去请求相应的api就能得到一个镜像列表,其中包含了tag,至此问题就解决了大部分了。
如果你们的docke的私域仓库不是华为云的,那你可能需要查看你们的私域获取镜像列表的api,获取之后处理方式其实也和这个差不多。
我会在下面贴出整个脚本,同时脚本中对每一行代码都做了注释。
#docker容器名
SERVER_NAME=hello_image
#版本号
TAG=$2
#环境名称
ACTIVE=$1
#容器id
CID=$(docker ps | grep "$SERVER_NAME" | awk '{print $1}')
#镜像id
IID=$(docker images | grep "$SERVER_NAME" | awk '{print $3}')
#是否已经初始化TAG的标识
hasTag=0
#是否已经初始化部署环境
hasActive=0
#如果采用注入参数的方式注入tag,则不会获取最新的tag,所以tag为空时才需要获取最新的tag
if [[ -z $TAG ]];then
$token
#这个token为在发起下面带json的post请求后,获取其响应头中的的X-Subject-Token值
token=$(curl -X POST -H "Content-Type: application/json" -s -i -d '@token.json' https://iam.cn-north-4.myhuaweicloud.com/v3/auth/tokens?nocatalog=true | grep X-Subject-Token | awk '{print $2}')
#根据上面获取的token,将其添加到X-Auth-Token属性中,会返回一个tag的列表
tagList=$(curl -H "Content-Type: application/json" -H 'X-Auth-Token: '"${token}"'' -s https://swr-api.cn-north-4.myhuaweicloud.com/v2/manage/namespaces/xxx/repos/xxx/tags | tr ',' '\n' )
#匹配Tag->只保留第一个->去除符号'":'
tagList=$(echo "$tagList" | awk '/Tag/' | sed -n '1'p | tr -d '":')
#只匹配Tag后面的值,匹配出来的就是tag值
TAG=${tagList#*Tag}
#若未能匹配到tag值,则需要手动输入
if [[ -z $TAG ]]; then
read -p "can't get latest image tag,you need input your image tag:" TAG
fi
fi
if [[ $ACTIVE = qa ]] || [[ $ACTIVE = prod ]];then
hasActive=1
echo "loading active is correct:$ACTIVE"
fi
if [[ -n $TAG ]];then
hasTag=1
echo "Loading tag is $TAG"
fi
if ((hasTag==0));then
read -p 'please input your image tag:' TAG
echo -e "your tag is:"$TAG
fi
if [ -n "$CID" ]; then
echo "存在容器$SERVER_NAME, CID-$CID"
docker stop $CID
echo "容器已停止"
docker rm $CID
echo "容器已删除"
fi
#删除原来的dpms_prod使用的镜像
if [ -n "$IID" ]; then
echo "删除$SERVER_NAME:$TAG镜像,IID=$IID"
docker rmi $IID
else
echo "不存在$SERVER_NAME:$TAG镜像"
fi
docker pull image_name:$TAG
echo "镜像拉取完毕!"
# 运行docker容器
docker run --restart=always -d -e SPRING_PROFILES_ACTIVE=$ACTIVE -p 8080:8080 -v /var/log/vgc:/var/log/vgc -it --name $SERVER_NAME image_name:$TAG
echo "$SERVER_NAME容器创建并运行"
exit 0
请求所需的json文件,token.json放在和你的脚本文件同一个目录即可:
{
"auth": {
"identity": {
"methods": [
"password"
],
"password": {
"user": {
"name": "xxx",
"password": "xxx",
"domain": {
"name": "xxx"
}
}
}
},
"scope": {
"project": {
"name": "cn-north-4"
}
}
}
}
在上述代码及其请求文件中的XXX部分为你们公司或者个人自己在华为云上的相关信息,具体可参见以下文档说明:
获取IAM用户Token(使用密码)_统一身份认证服务 IAM_API参考_API_Token管理_华为云 (huaweicloud.com)
curl -X POST -H "Content-Type: application/json" -s -i -d '@token.json' https://iam.cn-north-4.myhuaweicloud.com/v3/auth/tokens?nocatalog=true
使用这个api获取的token是在response的header中,而不是body中,这点要注意了
查询镜像仓库列表_容器镜像服务 SWR_API参考_API_镜像仓库管理_华为云 (huaweicloud.com)
curl -H "Content-Type: application/json" -H 'X-Auth-Token: '"${token}"'' -s https://swr-api.cn-north-4.myhuaweicloud.com/v2/manage/namespaces/xxx/repos/xxx/tags
在这个请求中,header中的token需要作为变量传递进来,但是要注意传递时,header的正确拼接,不然curl也会报错,需要以如下的方式拼接token到header中。你们如果使用不同的方式注入进去这个token参数,报错了的话,你们可以通过打印的request的header哪里格式不对来做出调整。
-H 'X-Auth-Token: '"${token}"''
请求体中包含了密码,建议不要随意转发这个文件。
对于上面没解释的一些管道命令,对其做出解释:
tr ',' '\n'
#使用tr将','替换成换行符,因为用curl输出的response是没有换行的,所以我们需要手动加上换行,以方便换行。
if [[ -z $TAG ]]
if [[ -n $TAG ]]
#我们在使用shell脚本的if时,加入参数-z,如果TAG为空,则返回真;加入参数-n,则TAG不为空时才为真。同时我们#要注意在使用shell的if语句时,一定不要少打空格,不然语法就会不符合规范。
最后补充一点,这个脚本也是可以在执行的时候就注入参数的,比如你的脚本文件是deploy.sh,那么你在当前目录执行以下命令即可:
sh deploy.sh "qa" "2022-01-12"
#第一个参数qa为你要部署的环境,这个是和springboot结合的。
#第二个参数 2022-01-12 是你要部署的项目的镜像的tag或者最新tag。
如果你们有更好的解决方式,欢迎在下方留言。
引用的参考资料:
https://blog.youkuaiyun.com/weixin_42939779/article/details/121104794
查询镜像仓库列表_容器镜像服务 SWR_API参考_API_镜像仓库管理_华为云 (huaweicloud.com)
获取IAM用户Token(使用密码)_统一身份认证服务 IAM_API参考_API_Token管理_华为云 (huaweicloud.com)