Docker镜像同步,解决镜像拉取失败
【代码】Docker镜像同步,解决镜像拉取失败。
·
工作流目录
.github/ISSUE_TEMPLATE
.github/workflows
工作流关键文件
#issue模板
cat mirror.md
=====================================================
---
name: hub-mirror issue template
about: 用于执行 hub-mirror-by-issue workflow 的 issue 模板
title: "[原镜像名称IMAGE_NAME]:busybox[同步后镜像名称NEW_NAME]:busybox[镜像版本IMAGE_VERSION]:latest[仓库地址TARGET_REGISTRY]:registry.cn-hangzhou.aliyuncs.com[空间名称TARGET_REPOSITORY]:library[平台 amd64(默认)、arm64、arm/v7等等TARGET_ARCH]:amd64"
labels: ["hub-mirror"]
---
**[原镜像名称IMAGE_NAME]**
<默认:busybox,请改为你需要的>
**[同步后镜像名称NEW_NAME]**
<默认:busybox,请改为你需要的>
**[镜像版本IMAGE_VERSION]**
<默认:latest,请改为你需要的>
**[仓库地址TARGET_REGISTRY]**
<默认:registry.cn-hangzhou.aliyuncs.com,请改为你需要的>
**[空间名称TARGET_REPOSITORY]**
<默认:library,请改为你需要的>
**[平台 amd64(默认)、arm64、arm/v7等等TARGET_ARCH]**
<默认:amd64,请改为你需要的>
=====================================================
#工作流模板
cat hub-mirror-by-issue.yaml
=====================================================
name: hub-mirror-by-issue
on:
issues:
types:
- opened
# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
permissions:
issues: write
jobs:
build:
runs-on: ubuntu-latest
if: contains(github.event.issue.labels.*.name, 'hub-mirror')
env:
QYWX_ROBOT_URL: "${{ secrets.QYWX_ROBOT_URL }}"
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: "${{ secrets.HUB_MIRROR_BY_ISSUE_TOKEN }}"
- name: Print image info to comment
id: print-image-info
env:
GH_TOKEN: "${{ github.token }}"
TITLE: "${{ github.event.issue.title }}"
run: |
#[原镜像名称IMAGE_NAME]:busybox[同步后镜像名称NEW_NAME]:busybox[镜像版本IMAGE_VERSION]:latest[仓库地址TARGET_REGISTRY]:registry.cn-hangzhou.aliyuncs.com[空间名称TARGET_REPOSITORY]:library[平台 amd64(默认)、arm64、arm/v7等等TARGET_ARCH]:amd64
# 原始镜像
IMAGE_NAME="$(echo "${TITLE}" | awk -F ":" '{print $2}' | awk -F "[" '{print $1}' | awk '{print $1}')"
echo "原始镜像:${IMAGE_NAME}"
# 同步后镜像
NEW_NAME="$(echo "${TITLE}" | awk -F ":" '{print $3}' | awk -F "[" '{print $1}' | awk '{print $1}')"
echo "同步后镜像:${NEW_NAME}"
# 镜像版本tag
IMAGE_VERSION="$(echo "${TITLE}" | awk -F ":" '{print $4}' | awk -F "[" '{print $1}' | awk '{print $1}')"
echo "镜像版本tag:${IMAGE_VERSION}"
# 仓库地址
TARGET_REGISTRY="$(echo "${TITLE}" | awk -F ":" '{print $5}' | awk -F "[" '{print $1}' | awk '{print $1}')"
echo "仓库地址:${TARGET_REGISTRY}"
# 仓库名称空间
TARGET_REPOSITORY="$(echo "${TITLE}" | awk -F ":" '{print $6}' | awk -F "[" '{print $1}' | awk '{print $1}')"
echo "仓库名称空间:${TARGET_REPOSITORY}"
# 架构
TARGET_ARCH="$(echo "${TITLE}" | awk -F ":" '{print $7}' | awk -F "[" '{print $1}' | awk '{print $1}')"
echo "架构:${TARGET_ARCH}"
gh issue comment "${{ github.event.issue.html_url }}" -b "$(echo -e "原始镜像:${IMAGE_NAME}\n同步后镜像:${NEW_NAME}\n镜像版本tag:${IMAGE_VERSION}\n仓库地址:${TARGET_REGISTRY}\n仓库名称空间:${TARGET_REPOSITORY}\n架构:${TARGET_ARCH}")"
gh issue comment "${{ github.event.issue.html_url }}" -b "镜像 ${IMAGE_NAME} 同步中...[详情请查看](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) 如果还需要同步, 请重新提交issue"
echo "image_name=${IMAGE_NAME}" >>"${GITHUB_OUTPUT}"
echo "new_name=${NEW_NAME}" >>"${GITHUB_OUTPUT}"
echo "image_version=${IMAGE_VERSION}" >>"${GITHUB_OUTPUT}"
echo "target_registry=${TARGET_REGISTRY}" >>"${GITHUB_OUTPUT}"
echo "target_repository=${TARGET_REPOSITORY}" >>"${GITHUB_OUTPUT}"
echo "target_arch=${TARGET_ARCH}" >>"${GITHUB_OUTPUT}"
- name: Login to Docker Registry
env:
GH_TOKEN: "${{ github.token }}"
IMAGE_NAME: "${{ steps.print-image-info.outputs.image_name }}"
NEW_NAME: "${{ steps.print-image-info.outputs.new_name }}"
IMAGE_VERSION: "${{ steps.print-image-info.outputs.image_version }}"
TARGET_REGISTRY: "${{ steps.print-image-info.outputs.target_registry }}"
TARGET_REPOSITORY: "${{ steps.print-image-info.outputs.target_repository }}"
TARGET_ARCH: "${{ steps.print-image-info.outputs.target_arch }}"
run: |
docker login -u "${{ secrets.DOCKER_USERNAME }}" -p "${{ secrets.DOCKER_PASSWORD }}" "${TARGET_REGISTRY}"
- name: Pull, tag, and push Docker image
env:
GH_TOKEN: "${{ github.token }}"
IMAGE_NAME: "${{ steps.print-image-info.outputs.image_name }}"
NEW_NAME: "${{ steps.print-image-info.outputs.new_name }}"
IMAGE_VERSION: "${{ steps.print-image-info.outputs.image_version }}"
TARGET_REGISTRY: "${{ steps.print-image-info.outputs.target_registry }}"
TARGET_REPOSITORY: "${{ steps.print-image-info.outputs.target_repository }}"
TARGET_ARCH: "${{ steps.print-image-info.outputs.target_arch }}"
run: |
if [ "${TARGET_ARCH}" != "" ]; then
docker pull --platform "${TARGET_ARCH}" "${IMAGE_NAME}:${IMAGE_VERSION}"
else
docker pull "${IMAGE_NAME}:${IMAGE_VERSION}"
fi
docker tag "${IMAGE_NAME}:${IMAGE_VERSION}" "${TARGET_REGISTRY}/${TARGET_REPOSITORY}/${NEW_NAME}:${IMAGE_VERSION}"
docker push "${TARGET_REGISTRY}/${TARGET_REPOSITORY}/${NEW_NAME}:${IMAGE_VERSION}"
- name: qyweixin send message
if: ${{ env.QYWX_ROBOT_URL != '' }}
uses: chf007/action-wechat-work@master
env:
WECHAT_WORK_BOT_WEBHOOK: "${{secrets.QYWX_ROBOT_URL}}"
IMAGE_URL: "${{ steps.print-image-info.outputs.target_registry }}/${{ steps.print-image-info.outputs.target_repository }}/${{ steps.print-image-info.outputs.new_name }}:${{ steps.print-image-info.outputs.image_version }}"
with:
msgtype: markdown
content: |
# 镜像同步成功
```
"${{ env.IMAGE_URL }}"
```
- name: Close issue
env:
GH_TOKEN: "${{ github.token }}"
IMAGE_NAME: "${{ steps.print-image-info.outputs.image_name }}"
NEW_NAME: "${{ steps.print-image-info.outputs.new_name }}"
IMAGE_VERSION: "${{ steps.print-image-info.outputs.image_version }}"
TARGET_REGISTRY: "${{ steps.print-image-info.outputs.target_registry }}"
TARGET_REPOSITORY: "${{ steps.print-image-info.outputs.target_repository }}"
TARGET_ARCH: "${{ steps.print-image-info.outputs.target_arch }}"
run: |
gh issue comment "${{ github.event.issue.html_url }}" -b "$(echo -e "镜像同步完成 ${NEW_NAME} ,新的镜像 ${TARGET_REGISTRY}/${TARGET_REPOSITORY}/${NEW_NAME}:${IMAGE_VERSION}\n\n快速拉取命令,Docker客户端\n\`\`\`sh\ndocker image pull ${TARGET_REGISTRY}/${TARGET_REPOSITORY}/${NEW_NAME}:${IMAGE_VERSION}\n\`\`\`\n\nContainerd客户端拉取命令\n\`\`\`sh\nctr -n k8s.io image pull ${TARGET_REGISTRY}/${TARGET_REPOSITORY}/${NEW_NAME}:${IMAGE_VERSION}\n\`\`\`\n")"
gh issue edit "${{ github.event.issue.html_url }}" --add-label "succeeded" -b "IMAGE SYNC"
gh issue close "${{ github.event.issue.html_url }}" --reason "completed"
- name: Failed Sync and Close issue
if: failure()
env:
GH_TOKEN: "${{ github.token }}"
IMAGE_NAME: "${{ steps.print-image-info.outputs.image_name }}"
NEW_NAME: "${{ steps.print-image-info.outputs.new_name }}"
IMAGE_VERSION: "${{ steps.print-image-info.outputs.image_version }}"
TARGET_REGISTRY: "${{ steps.print-image-info.outputs.target_registry }}"
TARGET_REPOSITORY: "${{ steps.print-image-info.outputs.target_repository }}"
TARGET_ARCH: "${{ steps.print-image-info.outputs.target_arch }}"
run: |
gh issue comment "${{ github.event.issue.html_url }}" -b "镜像 ${IMAGE_NAME} 同步失败...[详情请查看](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}),请检查 image参数,如果还需要同步,请重新提交正确的issue"
gh issue edit "${{ github.event.issue.html_url }}" --add-label "failure" -b "IMAGE SYNC"
gh issue close "${{ github.event.issue.html_url }}" --reason "not planned"
批量版关键文件】
=> root @ almalinux: /tmp/docker-xxx------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- main (1!)
➜ cat .github/ISSUE_TEMPLATE/mirror-multiple.md
---
name: hub-mirror-multiple issue template
about: 用于执行 hub-mirror-by-issue-multiple workflow 的 issue 模板
title: "[仓库地址TARGET_REGISTRY]:registry.cn-hangzhou.aliyuncs.com[空间名称TARGET_REPOSITORY]:library[平台 amd64(默认)、arm64、arm/v7等等TARGET_ARCH]:amd64"
labels: ["hub-mirror-multiple"]
---
**[需要同步的镜像列表,根据你的需求增加与减少]**
busybox:latest
nginx:latest
=> root @ almalinux: /tmp/docker-xxx------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- main (1!)
➜ cat .github/workflows/hub-mirror-by-issue-multiple.yaml
name: hub-mirror-by-issue-multiple
on:
issues:
types:
- opened
# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
permissions:
issues: write
jobs:
build:
runs-on: ubuntu-latest
if: contains(github.event.issue.labels.*.name, 'hub-mirror-multiple')
env:
QYWX_ROBOT_URL: "${{ secrets.QYWX_ROBOT_URL }}"
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: "${{ secrets.DOCKER_XXX_TOKEN }}"
- name: Print image info to comment
id: print-image-info
env:
GH_TOKEN: "${{ github.token }}"
TITLE: "${{ github.event.issue.title }}"
BODY: "${{ github.event.issue.body }}"
run: |
# [仓库地址TARGET_REGISTRY]:registry.cn-hangzhou.aliyuncs.com[空间名称TARGET_REPOSITORY]:library[平台 amd64(默认)、arm64、arm/v7等等TARGET_ARCH]:amd64
# 仓库地址
TARGET_REGISTRY="$(echo "${TITLE}" | awk -F ":" '{print $2}' | awk -F "[" '{print $1}' | awk '{print $1}')"
echo "仓库地址:${TARGET_REGISTRY}"
# 仓库名称空间
TARGET_REPOSITORY="$(echo "${TITLE}" | awk -F ":" '{print $3}' | awk -F "[" '{print $1}' | awk '{print $1}')"
echo "仓库名称空间:${TARGET_REPOSITORY}"
# 架构
TARGET_ARCH="$(echo "${TITLE}" | awk -F ":" '{print $4}' | awk -F "[" '{print $1}' | awk '{print $1}')"
echo "架构:${TARGET_ARCH}"
reg_exp="^[a-z0-9\/\:\.\-]+$"
echo "###需要同步的镜像清单" >"image.txt"
IFS=$'\n'
for item in ${BODY}; do
item="$(echo "${item}" | awk '{gsub(/ /,"",$0);print $0}' | awk '{print $1}')"
if [[ "${item}" =~ ${reg_exp} ]]; then
echo "${item}" >>"image.txt"
fi
done
IMAGE_TXT="$(cat image.txt)"
gh issue comment "${{ github.event.issue.html_url }}" -b "$(echo -e "\n镜像仓库:${TARGET_REGISTRY}\n仓库名称空间:${TARGET_REPOSITORY}\n架构:${TARGET_ARCH}\n\`\`\`sh\n${IMAGE_TXT}\n\`\`\`\n")"
gh issue comment "${{ github.event.issue.html_url }}" -b "镜像同步中...[详情请查看](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) 如果还需要同步, 请重新提交issue"
echo "target_registry=${TARGET_REGISTRY}" >>"${GITHUB_OUTPUT}"
echo "target_repository=${TARGET_REPOSITORY}" >>"${GITHUB_OUTPUT}"
echo "target_arch=${TARGET_ARCH}" >>"${GITHUB_OUTPUT}"
- name: Login to Docker Registry
env:
GH_TOKEN: "${{ github.token }}"
TARGET_REGISTRY: "${{ steps.print-image-info.outputs.target_registry }}"
TARGET_REPOSITORY: "${{ steps.print-image-info.outputs.target_repository }}"
TARGET_ARCH: "${{ steps.print-image-info.outputs.target_arch }}"
run: |
docker login -u "${{ secrets.DOCKER_USERNAME }}" -p "${{ secrets.DOCKER_PASSWORD }}" "${TARGET_REGISTRY}"
- name: Pull, tag, and push Docker image
id: pull-tag-push-image
env:
GH_TOKEN: "${{ github.token }}"
TARGET_REGISTRY: "${{ steps.print-image-info.outputs.target_registry }}"
TARGET_REPOSITORY: "${{ steps.print-image-info.outputs.target_repository }}"
TARGET_ARCH: "${{ steps.print-image-info.outputs.target_arch }}"
run: |
if [ "${TARGET_ARCH}" != "" ]; then
bash docker_image_pull.sh --image-from-file="image.txt" --tag --push --repo="${TARGET_REGISTRY}/${TARGET_REPOSITORY}" --arch="${TARGET_ARCH}"
else
bash docker_image_pull.sh --image-from-file="image.txt" --tag --push --repo="${TARGET_REGISTRY}/${TARGET_REPOSITORY}"
fi
echo "build_log<<EOF" >>"${GITHUB_OUTPUT}"
cat build.log >>"${GITHUB_OUTPUT}"
echo "EOF" >>"${GITHUB_OUTPUT}"
- name: qyweixin send message
if: ${{ env.QYWX_ROBOT_URL != '' }}
uses: chf007/action-wechat-work@master
env:
WECHAT_WORK_BOT_WEBHOOK: "${{secrets.QYWX_ROBOT_URL}}"
IMAGE_URL: "${{ steps.pull-tag-push-image.outputs.build_log }}"
with:
msgtype: markdown
content: |
# 镜像同步成功
```
"${{ env.IMAGE_URL }}"
```
- name: Close issue
env:
GH_TOKEN: "${{ github.token }}"
TARGET_REGISTRY: "${{ steps.print-image-info.outputs.target_registry }}"
TARGET_REPOSITORY: "${{ steps.print-image-info.outputs.target_repository }}"
TARGET_ARCH: "${{ steps.print-image-info.outputs.target_arch }}"
BUILD_LOG: "${{ steps.pull-tag-push-image.outputs.build_log }}"
run: |
gh issue comment "${{ github.event.issue.html_url }}" -b "$(echo -e "镜像同步完成,详细日志\n\`\`\`sh\n${BUILD_LOG}\n\`\`\`\n")"
gh issue edit "${{ github.event.issue.html_url }}" --add-label "succeeded" -b "IMAGE SYNC"
gh issue close "${{ github.event.issue.html_url }}" --reason "completed"
- name: Failed Sync and Close issue
if: failure()
env:
GH_TOKEN: "${{ github.token }}"
TARGET_REGISTRY: "${{ steps.print-image-info.outputs.target_registry }}"
TARGET_REPOSITORY: "${{ steps.print-image-info.outputs.target_repository }}"
TARGET_ARCH: "${{ steps.print-image-info.outputs.target_arch }}"
BUILD_LOG: "${{ steps.pull-tag-push-image.outputs.build_log }}"
run: |
gh issue comment "${{ github.event.issue.html_url }}" -b "镜像同步失败...[详情请查看](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}),请检查参数..."
gh issue edit "${{ github.event.issue.html_url }}" --add-label "failure" -b "IMAGE SYNC"
gh issue close "${{ github.event.issue.html_url }}" --reason "not planned"
=> root @ almalinux: /tmp/docker-xxx------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- main (1!)
➜ cat .editorconfig
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
# For all *.sh file indent_size is 4, indent_style is space
[*.sh]
indent_style = space
indent_size = 4
# For all *.lua file indent_size is 2, indent_style is space
[*.lua]
indent_style = space
indent_size = 2
# For all *.yml and *.yaml file indent_size is 2, indent_style is space
[*.{yml,yaml}]
indent_style = space
indent_size = 2
# For file name is Dockerfile indent_size is 4, indent_style is space
[Dockerfile]
indent_style = space
indent_size = 4
=> root @ almalinux: /tmp/docker-xxx------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- main (1!)
➜ cat docker_image_pull.sh
#!/bin/bash
#
#******************************************************************************************
#Author: QianSong
#QQ: xxxxxxxxxx
#Date: 2024-09-06
#FileName: docker_image_pull.sh
#URL: https://github.com
#Description: The test script
#Copyright (C): QianSong 2024 All rights reserved
#******************************************************************************************
#######################################
# 打印使用方法
# Globals:
# none
# Arguments:
# none
# Outputs:
# none
# Returns:
# none
#######################################
function print_usage() {
echo "用法:bash $0 [选项] [选项值]"
echo ""
echo "选项:"
echo " --image 镜像列表: --image=iamge1,image2,image3.... (与--image-from-file互斥)"
echo " --image-from-file 镜像清单文件: --image-from-file=file (与--image互斥)"
echo " -t, --tag 启用tag,默认不会启用tag,如果启用--tag,必须同时启用--repo"
echo " -p, --push 启用push,默认不会push,如果启用--push,必须同时启用--tag与--repo"
echo " --repo 镜像仓库域名: --repo=example.repo.com"
echo " --arch 镜像架构: --arch=[amd64,arm64,arm/v7,arm/v6,ppc64le,s390x]"
echo " -h, --help 输出此帮助信息并退出"
}
#######################################
# 初始化全局变量
# Globals:
# ${image_list} ${image_file} ${enable_tag}
# ${enable_push} ${repo_domain}
# Arguments:
# none
# Outputs:
# none
# Returns:
# none
#######################################
function init_global_vars() {
#work_dir
work_dir="$(dirname "$(realpath -s "$0")")"
#work genarl var
image_list=""
image_file=""
enable_tag=0
enable_push=0
repo_domain=""
target_arch="amd64"
#color
hei_color="\033[1;30m"
hong_color="\033[1;31m"
lv_color="\033[1;32m"
huang_color="\033[1;33m"
lan_color="\033[1;34m"
zi_color="\033[1;35m"
tianlan_color="\033[1;36m"
bai_color="\033[1;37m"
normal_color="\033[0m"
}
#######################################
# 获取用户传入的脚本参数,并作相应处理
# Globals:
# ${image_list} ${image_file} ${enable_tag}
# ${enable_push} ${repo_domain}
# Arguments:
# "$@"
# Outputs:
# none
# Returns:
# none
#######################################
function get_user_option_paramater() {
if [ $# -eq 0 ]; then
print_usage
exit 0
fi
local opts
opts="$(getopt -q -o t,p,h -l image:,image-from-file:,tag,push,repo:,arch:,help -- "$@")"
if [ $? -ne 0 ]; then
print_usage
exit 1
fi
eval set -- "${opts}"
while true; do
case "$1" in
--image)
local danger_exp1="[ ]+"
if [[ ! "$2" =~ ${danger_exp1} ]]; then
image_list="$2"
else
echo -e "${hong_color}Bad option ${bai_color}$1 $2 \n${zi_color}String contain spaces ${bai_color}($2)${normal_color}"
exit 1
fi
shift 2
;;
--image-from-file)
local danger_exp2="^\/+$"
local trim_space2
trim_space2="$(echo "$2" | awk '{gsub(/ /,"",$0); print $0}')"
if [[ ! "${trim_space2}" =~ ${danger_exp2} ]] && [ -f "$2" ]; then
image_file="$2"
else
echo -e "${hong_color}Bad option ${bai_color}$1 $2 \n${zi_color}No such file ${bai_color}($2)${zi_color} Or file can not be ${bai_color}\"/\"${normal_color}"
exit 1
fi
shift 2
;;
-t | --tag)
enable_tag=1
shift 1
;;
-p | --push)
enable_push=1
shift 1
;;
--repo)
local danger_exp3="(--)|(\/\/)|[ ]+"
local arepo_exp1 arepo_exp2
arepo_exp1="^([a-z0-9])([a-z0-9\.\/\-])+(\/)([a-z0-9])+$"
arepo_exp2="^([a-z0-9])([a-z0-9\.\/\-])+(\/)([a-z0-9])+(\/)$"
local brepo_exp1 brepo_exp2
brepo_exp1="^([a-z0-9])([a-z0-9\.\-])+([a-z0-9])$"
brepo_exp2="^([a-z0-9])([a-z0-9\.\-])+(\/)$"
if [[ "$2" =~ ${danger_exp3} ]]; then
echo -e "${hong_color}Bad option ${bai_color}$1 $2 \n${zi_color}String contain danger stuff be like \"//\" \"--\" and space ${bai_color}($2)${normal_color}"
exit 1
elif [[ "$2" =~ ${arepo_exp1} ]] || [[ "$2" =~ ${arepo_exp2} ]] || [[ "$2" =~ ${brepo_exp1} ]] || [[ "$2" =~ ${brepo_exp2} ]]; then
repo_domain="$2"
else
echo -e "${hong_color}Bad option ${bai_color}$1 $2 \n${zi_color}String is a bad domain ${bai_color}($2)${normal_color}"
exit 1
fi
shift 2
;;
--arch)
local reg_exp_arch="^amd64$|^arm64$|^arm/v7$|^arm/v6$|^ppc64le$|^s390x$|^$"
if [[ "$2" =~ ${reg_exp_arch} ]]; then
case "$2" in
"amd64")
target_arch="amd64"
;;
"arm64")
target_arch="arm64"
;;
"arm/v7")
target_arch="arm/v7"
;;
"arm/v6")
target_arch="arm/v6"
;;
"ppc64le")
target_arch="ppc64le"
;;
"s390x")
target_arch="s390x"
;;
"")
target_arch="amd64"
;;
esac
else
echo -e "${hong_color}Bad option ${bai_color}$1 $2 \n${zi_color}String is a bad arch for docker ${bai_color}($2)${normal_color}"
exit 1
fi
shift 2
;;
-h | --help)
print_usage
shift 1
exit 0
;;
--)
shift 1
break
;;
*)
echo -e "${hong_color}Internal error${normal_color}"
exit 1
;;
esac
done
}
#######################################
# 检查用户传入的参数,严格限制参数的依赖性
# Globals:
# none
# Arguments:
# none
# Outputs:
# none
# Returns:
# none
#######################################
function check_paramater_to_work() {
# NOTE: 如果 --image 与 --image-from-file 都没有指定,则阻止运行
if [ -z "${image_list}" ] && [ -z "${image_file}" ]; then
echo -e "${hong_color}Error: ${bai_color}--image 或 --image-from-file 没有指定,不能继续...${normal_color}"
exit 1
fi
# NOTE: 如果 --image 与 --image-from-file 都指定,则阻止运行
if [ -n "${image_list}" ] && [ -n "${image_file}" ]; then
echo -e "${hong_color}Error: ${bai_color}--image 与 --image-from-file 互斥且只能指定其中一个,不能继续...${normal_color}"
exit 1
fi
# NOTE: 如果 --tag 指定,然而却没有指定 --repo,则阻止运行
if [ "${enable_tag}" == "1" ]; then
if [ -z "${repo_domain}" ]; then
echo -e "${hong_color}Error: ${bai_color}--tag 与 --repo 强行依赖,缺少 --repo,不能继续...${normal_color}"
exit 1
fi
fi
# NOTE: 如果 --push 指定,然而却没有指定 --repo 与 --tag,则阻止运行
if [ "${enable_push}" == "1" ]; then
if [ -z "${repo_domain}" ] || [ "${enable_tag}" == "0" ]; then
echo -e "${hong_color}Error: ${bai_color}--push 与 --repo\--tag 强行依赖,缺少 --repo\--tag,不能继续...${normal_color}"
exit 1
fi
fi
}
#######################################
# LOGO
# Globals:
# none
# Arguments:
# none
# Outputs:
# none
# Returns:
# none
#######################################
function print_logo() {
echo -e "${zi_color}▜▘▞▀▖▙▗▌▞▀▖▛▀▘ ▞▀▖▞▀▖▙▗▌▛▀▖▛▀▖▛▀▘▞▀▖▞▀▖${normal_color}"
echo -e "${zi_color}▐ ▙▄▌▌▘▌▌▄▖▙▄ ▌ ▌ ▌▌▘▌▙▄▘▙▄▘▙▄ ▚▄ ▚▄${normal_color}"
echo -e "${zi_color}▐ ▌ ▌▌ ▌▌ ▌▌ ▌ ▖▌ ▌▌ ▌▌ ▌▚ ▌ ▖ ▌▖ ▌${normal_color}"
echo -e "${zi_color}▀▘▘ ▘▘ ▘▝▀ ▀▀▘▀▀▀▝▀ ▝▀ ▘ ▘▘ ▘ ▘▀▀▘▝▀ ▝▀${normal_color}"
}
#######################################
# 镜像拉取函数
# Globals:
# none
# Arguments:
# none
# Outputs:
# none
# Returns:
# none
#######################################
function pull_image_from_docker() {
local image_pull_list=()
if [ -n "${image_list}" ]; then
local item
IFS=,
for item in ${image_list}; do
image_pull_list+=("${item}")
done
elif [ -n "${image_file}" ]; then
local item
local contain_space_exp="[[:blank:]]+"
local contain_jing_exp="^[[:blank:]]*#"
while IFS=$'\n' read -r item; do
if [[ "${#item}" -gt 0 ]] && [[ ! "${item}" =~ ${contain_space_exp} ]] && [[ ! "${item}" =~ ${contain_jing_exp} ]]; then
image_pull_list+=("${item}")
fi
done <"${image_file}"
fi
local image pull_status image_tag push_status
declare -a failed_images
declare -a succeed_images
declare -a pushed_images
failed_images=()
succeed_images=()
pushed_images=()
local arepo_exp1 arepo_exp2
arepo_exp1="^([a-z0-9])([a-z0-9\.\/\-])+(\/)([a-z0-9])+$"
arepo_exp2="^([a-z0-9])([a-z0-9\.\/\-])+(\/)([a-z0-9])+(\/)$"
local brepo_exp1 brepo_exp2
brepo_exp1="^([a-z0-9])([a-z0-9\.\-])+([a-z0-9])$"
brepo_exp2="^([a-z0-9])([a-z0-9\.\-])+(\/)$"
IFS=$' \n\t'
for image in "${image_pull_list[@]}"; do
echo
echo -e "${lv_color}开始拉取镜像 ${bai_color}${image} ${lv_color}...${normal_color}"
sleep 2
docker image pull --platform "${target_arch}" "${image}"
pull_status="$?"
if [ "${pull_status}" -ne 0 ]; then
echo
echo -e "${hong_color}Bad: ${bai_color}镜像 ${image} 拉取失败...${normal_color}"
failed_images+=("${image}")
continue
else
echo
echo -e "${lv_color}Good: ${bai_color}镜像 ${image} 拉取完毕...${normal_color}"
succeed_images+=("${image}")
if [ "${enable_tag}" == "1" ]; then
if [[ "${repo_domain}" =~ ${arepo_exp1} ]]; then
image_tag="${repo_domain}/${image##*/}"
elif [[ "${repo_domain}" =~ ${arepo_exp2} ]]; then
image_tag="${repo_domain}${image##*/}"
elif [[ "${repo_domain}" =~ ${brepo_exp1} ]]; then
image_tag="${repo_domain}/library/${image##*/}"
elif [[ "${repo_domain}" =~ ${brepo_exp2} ]]; then
image_tag="${repo_domain}library/${image##*/}"
else
echo -e "${hong_color}Error: ${bai_color}糟糕的镜像仓库域名 ${lv_color}${repo_domain} ${bai_color},请检查后重试...${normal_color}"
exit 1
fi
echo
echo -e "${lv_color}开始标记 ${bai_color}${image} ${lv_color}为${bai_color} ${image_tag} ${lv_color}...${normal_color}"
docker image tag "${image}" "${image_tag}"
# NOTE: 如果启用 --push,则推送镜像
if [ "${enable_push}" == "1" ]; then
echo
echo -e "${lv_color}开始推送 ${bai_color}${image_tag} ${lv_color}...${normal_color}"
docker image push "${image_tag}"
push_status="$?"
if [ "${push_status}" -ne 0 ]; then
echo
echo -e "${hong_color}Error: ${bai_color}镜像 ${image_tag} 推送失败,操作终止,请排查原因后继续...${normal_color}"
exit 1
else
pushed_images+=("${image_tag}")
fi
fi
fi
fi
done
# 输出操作结果概览
echo
print_logo
if [ "${#succeed_images[@]}" -ne 0 ]; then
echo
echo -e "${lv_color}成功的镜像列表:${normal_color}"
echo -e "--------------------------------------"
IFS=$' \n\t'
for item in "${succeed_images[@]}"; do
echo -e "${item}"
done
fi
if [ "${#failed_images[@]}" -ne 0 ]; then
echo
echo -e "${hong_color}失败的镜像列表:${normal_color}"
echo -e "--------------------------------------"
IFS=$' \n\t'
for item in "${failed_images[@]}"; do
echo -e "${item}"
done
fi
if [ "${#pushed_images[@]}" -ne 0 ]; then
echo
echo -e "${hong_color}新的镜像列表:${normal_color}"
echo -e "--------------------------------------"
IFS=$' \n\t'
for item in "${pushed_images[@]}"; do
echo -e "${item}"
done
fi
# NOTE:生成构建报告log
{
if [ "${#succeed_images[@]}" -ne 0 ]; then
echo
echo -e "成功的镜像列表:"
echo -e "--------------------------------------"
IFS=$' \n\t'
for item in "${succeed_images[@]}"; do
echo -e "${item}"
done
fi
if [ "${#failed_images[@]}" -ne 0 ]; then
echo
echo -e "失败的镜像列表:"
echo -e "--------------------------------------"
IFS=$' \n\t'
for item in "${failed_images[@]}"; do
echo -e "${item}"
done
fi
if [ "${#pushed_images[@]}" -ne 0 ]; then
echo
echo -e "新的镜像列表:"
echo -e "--------------------------------------"
IFS=$' \n\t'
for item in "${pushed_images[@]}"; do
echo -e "${item}"
done
fi
} >"${work_dir:?}/build.log"
}
#######################################
# 检查docker是否安装
# Globals:
# none
# Arguments:
# none
# Outputs:
# none
# Returns:
# 1: 表示没有安装或没有运行
# 0: 表示一切正常,可以继续
#######################################
function check_if_docker_installed() {
local docker_pid_num
docker_pid_num="$(ps -ef | awk '{if ($8 ~ "dockerd$") {k++}} END{print k}')"
if ! type docker >/dev/null 2>&1; then
return 1
fi
if [[ "${docker_pid_num:-0}" -eq 0 ]]; then
return 1
fi
return 0
}
#######################################
# 脚本的入口,程序执行的起点函数main
# Globals:
# none
# Arguments:
# "$@"
# Outputs:
# none
# Returns:
# none
#######################################
function main() {
init_global_vars
if ! check_if_docker_installed; then
echo -e "${hong_color}Error: ${bai_color}docker 没有安装或没有运行,不能继续...${normal_color}"
exit 1
fi
get_user_option_paramater "$@"
check_paramater_to_work
pull_image_from_docker
}
main "$@"

更多推荐

所有评论(0)