1. 博客/

批量自动构建docker镜像的shell脚本

·580 字·3 分钟
Docker Shell

背景
#

目前,由于公司多个相互隔离环境并存,各个环境都部署有容器管理平台,当有docker image更新的时候,就需要在每个环境都修改Dockerfile并执行docker build & docker push到公共镜像仓库的操作,为了减少重复性的工作,我就写了一个自动构建镜像的脚本,只需要在一个环境中准备好构建镜像的Dockerfile及依赖文件,执行脚本完成构建和推送,然后打包构建镜像的文件夹并传输到另一环境,执行脚本就可以自动完成

脚本运行示例
#

示例

构建脚本的目录结构
#

目录

01.20171229文件夹 <—> 要构建镜像的tag

构建镜像步骤
#

创建目录
#

$ cd /data/dcos
$ mkdir -p buildimages/01.20171229 log
$ cd buildimages/01.20171229
#创建各个需要build镜像的文件夹
$ mkdir centos7.2_tomcat7.0.72-all rhel7.2_tomcat7.0.63-jdk1.6.0_45 ...

修改configfile
#

$ vim /data/dcos/buildimages/configfile
TargetRegistry:192.168.196.128:5000                              --> 当前环境镜像仓库地址
Registry_user:admin	                                             -->  仓库登录用户名
Registry_passwd:admin                                            -->  仓库认证密码

准备Dockerfile和依赖文件
#

#示例
$ ls centos7.2_tomcat7.0.72-all
Dockerfile  startServer.sh

构建镜像
#

$ bash /data/dcos/buildimages/build.sh 01.20171229               -->脚本要跟参数01.20171229

日志文件
#

$ less /data/dcos/buildimages/log/01.20171229.log                                        -->以tag命名的日志文件
Trying to pull repository 192.168.196.128:5000/admin/centos7.2_tomcat7.0.72-all ... 
01.20171221: Pulling from 192.168.196.128:5000/admin/centos7.2_tomcat7.0.72-all
4f4fb700ef54: Pulling fs layer
d8405e7a6b27: Pulling fs layer
02389d9a455d: Pulling fs layer
...中间省略...
a3eef13e30fb: Pull complete
2833ecd114e0: Pull complete
f8b56d99c9b0: Pull complete
adb966dc304e: Pull complete
Digest: sha256:861302f6da8e083b112d92fa153fc4dcde677f6d3e598ab22eea4289e312b08c
Sending build context to Docker daemon  5.12 kB^M
Step 1 : FROM 192.168.196.128:5000/admin/centos7.2_tomcat7.0.72-all:01.20171221
 ---> 09ce979d3860
Step 2 : USER root
 ---> Running in 9a072cdbee5e
 ---> cc3b6b1d9bf1
Removing intermediate container 9a072cdbee5e
Step 3 : COPY startServer.sh /app/bin/startServer.sh
 ---> 0d743c01403c
Removing intermediate container fbdd0d775d09
Step 4 : RUN chmod +x /app/bin/startServer.sh &&      chown -R dcos:docker /app/bin/startServer.sh
 ---> Running in 03b6f5d1d467
  ---> 0f6055d1b9c5
Removing intermediate container 03b6f5d1d467
Step 5 : USER dcos
 ---> Running in 6ac2a787ae71
 ---> ae33c0899e2a
Removing intermediate container 6ac2a787ae71
Successfully built ae33c0899e2a
The push refers to a repository [192.168.196.128:5000/admin/centos7.2_tomcat7.0.72-all]
e623fa631602: Preparing
473647768f24: Preparing
96bd6e1cc68c: Preparing
...中间省略...
473647768f24: Pushed
e623fa631602: Pushed
01.20171229: digest: sha256:1a5c012f2d7b4a627c5dc1aca22350d652676adf53adfde0d471943f4d390d4b size: 6798

压缩构建镜像的目录
#

$ tar cvf 01.20171229.tar /data/dcos/buildimages/01.20171229

跨环境自动构建镜像
#

传输01.20171229.tar文件并解压
#

$ cd /data/dcos/buildimages
$ tar xf 01.20171229.tar

查看并确认configfile
#

#示例
$ vim /data/dcos/buildimages/configfile
TargetRegistry:192.168.196.128:5000                                    --> 当前环境镜像仓库地址
Registry_user:admin
Registry_passwd:admin

构建镜像
#

$ bash /data/dcos/buildimages/build.sh 01.20171229

shell脚本
#

#!/bin/bash
#Date:2018-01-03
#version:3.0
#Author:Feixiang Fu
#Description:Auto-build images based on configfile && Auto-push images 
. /etc/init.d/functions

[ -z "$*" ] && echo "usage: "buildim.sh VERSIONDIR" (VERSIONDIR is the target image tag)" && exit 1

dir=/data/dcos/buildimages
build_dir=$dir/$1

if [ ! -d $build_dir ]; then
	action "目标目录${1}不存在" false 
	exit 1
fi

addr=`cat $dir/configfile | awk -F: '/^TargetRegistry/{print $2":"$3}'`
user=`cat $dir/configfile | awk -F: '/^Registry_user/{print $2}'`
passwd=`cat $dir/configfile | awk -F: '/^Registry_passwd/{print $2}'`

cd $build_dir

imagesdir_num=`ls -d $build_dir/*/|wc -l`
if [ $imagesdir_num -eq 0 ] ; then
	action "${1}目录下没有要构建的镜像文件夹" false
	exit 1
fi

docker login -u $user -p $passwd $addr &> /dev/null

if [ $? -eq 0 ] ; then
	action "登陆镜像仓库${addr}成功" 
else
	action "登陆镜像仓库${addr}失败" false
	exit 1
fi

declare -a localim

buildim(){

	cd $build_dir/$1 &> /dev/null
	if [ $? -ne 0 ] ;then
		echo "${1}为普通文件,略过" 
		continue
	fi

	if [ -f ./Dockerfile ] ;then

		sed -i -r "s#(FROM\s+)[^/]+(\/.*)#\1${addr}\2#" Dockerfile

		baseimage=`cat Dockerfile |grep FROM|cut -d" " -f2`
		baseimage_num=`docker images|awk '{print $1":"$2}'|grep "$baseimage"|wc -l`
		baseimage_name=`echo "$baseimage" | awk -F/ '{print $3}' `
		if [ $baseimage_num -eq 0 ] ; then
			echo -e "正在拉取\e[33m${baseimage_name}\e[0m"
			docker pull $baseimage >> $dir/log/${2}.log 2>&1 
			if [ $? -eq 0 ]; then
				action "拉取${baseimage_name}成功"
				localim[${#localim[*]}]=$baseimage
			else
				action "拉取${baseimage_name}失败" false
				continue
			fi
		fi

		path=`echo $baseimage |cut -d: -f1,2`
		newimage_name=`echo $baseimage_name|sed -r "s/([^:]+:).*/\1$2/"`
		echo -e "正在构建\e[33m${newimage_name}\e[0m"
		docker build -t $path:$2 ./ >> $dir/log/${2}.log 2>&1
		if [ $? -eq 0 ] ;then
			action "${newimage_name}构建成功"
			localim[${#localim[*]}]=$path:$2
		else
			action "${newimage_name}构建失败" false
			continue
		fi
	
		echo -e "正在推送\e[33m${newimage_name}\e[0m"
		docker push $path:$2 >> $dir/log/${2}.log 2>&1 
		if [ $? -eq 0 ] ;then
			action "${newimage_name}推送成功"
		else
			action "${newimage_name}推送失败" false
		fi
		
	else
		action "${1}目录下无Dockerfile" false	
	fi
}

for i in `ls $build_dir` ; do
	echo -e "\e[32m-------------------------------------------------------------------\e[0m"
	buildim $i $1
done

echo -e "\e[32m-------------------------------------------------------------------\e[0m"
echo "正在清理本地镜像文件"
for j in `seq $((${#localim[*]}-1)) -1 0` ;do
	localim_name=$(echo "${localim[$j]}"| awk -F/ '{print $3}')
	docker rmi ${localim[$j]} >> $dir/log/${1}.log 2>&1
	if [ $? -eq 0 ] ;then
                        action "${localim_name}清理成功"
        else
                        action "${localim_name}清理失败" false
        fi
done

echo -e "\e[32m-------------------------------------------------------------------\e[0m"
[ -f $dir/log/${1}.log ] && echo "logfile: $dir/log/${1}.log"