外观
Code Snippets
约 671 字大约 2 分钟
2025-09-11
Docker 增量镜像发布
docker_deploy.sh
#!/bin/bash
set -e
if [ $# -eq 0 ]; then
printf "用法: %s [多个待发布的文件或目录>] [-d 多个待删除的文件或目录] \n" "$(basename "$0")"
printf "可选参数:\n"
printf " -d delete_files 删除多个文件或目录\n"
exit 1
fi
## 使用本地脚本传递给远程调用,无需使用远程主机的上的脚本呢,顾注释
# 多个参数转为一个字符串后,再重新设置为多个参数
# 兼容 远程调用不能传递多个参数的情况
# read -r -a array <<< "$@"
# set -- "${array[@]}"
: "${docker_repo_ip:="10.230.50.188"}"
repository="${docker_repo_ip}:1121/hn_billing/ims"
docker_file="/app/billing/build_docker/ims/Dockerfile_ims_add"
: "${timestamp:=$(date "+%y%m%d-%H%M%S")}"
: "${currdir:="$(pwd)"}" # 执行当前脚本的目录
: "${basedir:="/app/billing/build_docker/ims/"}" # 镜像文件对应的本地工作目录
# 获取基于 basedir 的相对路径,即镜像中基于 workdir 的相对路径
rela_path() {
for file_or_dir in "$@"; do
file_or_dir="$(realpath "${file_or_dir}")" # 最后没有/
if [ "${file_or_dir}/" = "${basedir}" ]; then
echo "./"
else
if [ -f "$file_or_dir" ]; then
echo "${file_or_dir}" | sed "s|${basedir}||"
else
# 是目录,最后加/
echo "${file_or_dir}/" | sed "s|${basedir}||"
fi
fi
done
}
check_files_exist() {
for file in "$@"; do
if [ ! -e "${file}" ]; then
echo "ERROR: ${file} 文件或目录不存在,退出 ..."
# 强检查:如何文件不存在,直接退出脚本
exit 1
fi
done
return 0
}
while [[ $# -gt 0 ]]; do
case $1 in
-d)
shift
while [[ $# -gt 0 ]]; do
delete_files+=("$1")
shift
done
;;
*)
add_files+=("$1")
shift
;;
esac
done
deletestr=""
check_files_exist "${delete_files[@]}" # 强检查
if [ "${#delete_files[@]}" -gt 0 ]; then
# 待删除的文件的路径为基于 basedir 的相对路径
# 即:镜像内基于 currdir 的相对路径
dfiles_str=$(printf "%s " $(rela_path "${delete_files[@]}"))
deletestr="RUN rm -fr ${dfiles_str}\n"
# 删除主机上的文件
echo -e "删除文件: ${delete_files[@]} ..."
rm -r "${delete_files[@]}"
## 忽悠删除时文件报错,但是会导致b中心 deletestr 异常,顾注释
# warnings=$(rm -r "${delete_files[@]}" 2>&1 || true)
# if [ -n "${warnings}" ]; then
# echo "WARNNING: ${warnings}"
# fi
# echo ""
fi
# 压缩需要加入到镜像中的文件或目录
addstr=""
check_files_exist "${add_files[@]}"
if [ "${#add_files[@]}" -gt 0 ]; then
targz_file="${timestamp}.tar.gz"
echo -e "压缩文件: ${add_files[@]} ..."
# 在任何异常退出情况下,删除压缩包
trap "rm -fr ${targz_file} && echo \"删除压缩包 ${targz_file}\"" EXIT
errors=$(tar -czvf "${targz_file}" "${add_files[@]}" 2>&1 >/dev/null)
if [ -n "${errors}" ]; then
printf "ERROR: 不允许使用 \"../\" 父目录路径写法\n%s\n" "${errors}"
exit 1
fi
echo -e "生成压缩包: ${targz_file}\n"
addstr="ADD ${targz_file} $(rela_path "${currdir}")"
fi
tagid=$(docker images | grep "${repository} " | head -n 1 | awk {'print $2'})
echo -e "获取最新镜像tag: ${tagid} ..."
fromstr="From ${repository}:${tagid}"
echo -e "${fromstr}\n${deletestr}${addstr}" > "${docker_file}"
echo -e "生成 dockerfile 文件\n"
new_image="${repository}:${timestamp}"
echo -e "正在构建新镜像 ${new_image} ..."
docker build -t "${new_image}" -f "${docker_file}" . > /dev/null
rm "${docker_file}"
echo -e "新镜像构建完成!\n"
echo -e "正在发布新镜像 ${new_image} ..."
docker push "${new_image}" > /dev/null
echo -e "镜像发布完成!"