311 lines
6.7 KiB
Bash
Executable File
311 lines
6.7 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
##############################################################################
|
||
# Push Local Images to Harbor
|
||
# 将本地所有基础镜像推送到 Harbor
|
||
##############################################################################
|
||
|
||
set -euo pipefail
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Harbor 配置
|
||
HARBOR_IP="${HARBOR_IP:-192.168.1.83}"
|
||
HARBOR_HTTP_PORT="${HARBOR_HTTP_PORT:-8080}"
|
||
HARBOR_REGISTRY="${HARBOR_IP}:${HARBOR_HTTP_PORT}"
|
||
HARBOR_PROJECT="${HARBOR_PROJECT:-library}"
|
||
HARBOR_USERNAME="${HARBOR_USERNAME:-admin}"
|
||
HARBOR_PASSWORD="${HARBOR_PASSWORD:-admin123}"
|
||
|
||
# 日志函数
|
||
log_info() {
|
||
echo -e "${BLUE}ℹ${NC} $1"
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "${GREEN}✓${NC} $1"
|
||
}
|
||
|
||
log_warning() {
|
||
echo -e "${YELLOW}⚠${NC} $1"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}✗${NC} $1"
|
||
}
|
||
|
||
# 登录 Harbor
|
||
harbor_login() {
|
||
log_info "登录到 Harbor Registry..."
|
||
|
||
if echo "${HARBOR_PASSWORD}" | docker login "${HARBOR_REGISTRY}" -u "${HARBOR_USERNAME}" --password-stdin 2>/dev/null; then
|
||
log_success "登录成功"
|
||
return 0
|
||
else
|
||
log_error "登录失败"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 获取本地所有镜像
|
||
get_local_images() {
|
||
log_info "获取本地镜像列表..."
|
||
|
||
# 获取所有本地镜像,排除 Harbor 自身的镜像
|
||
docker images --format "{{.Repository}}:{{.Tag}}" | \
|
||
grep -v "^${HARBOR_REGISTRY}" | \
|
||
grep -v "<none>" | \
|
||
sort -u
|
||
}
|
||
|
||
# 过滤基础镜像
|
||
filter_base_images() {
|
||
log_info "过滤基础组件镜像..."
|
||
|
||
# 基础镜像关键词
|
||
local base_keywords=(
|
||
"alpine"
|
||
"ubuntu"
|
||
"debian"
|
||
"centos"
|
||
"fedora"
|
||
"nginx"
|
||
"redis"
|
||
"postgres"
|
||
"mysql"
|
||
"mongo"
|
||
"python"
|
||
"node"
|
||
"golang"
|
||
"openjdk"
|
||
"busybox"
|
||
"registry"
|
||
"k8s.gcr.io"
|
||
"registry.k8s.io"
|
||
"quay.io"
|
||
"ghcr.io"
|
||
"docker.io"
|
||
)
|
||
|
||
# 读取所有镜像
|
||
local images=()
|
||
while IFS= read -r image; do
|
||
images+=("$image")
|
||
done
|
||
|
||
# 过滤基础镜像
|
||
local filtered=()
|
||
for image in "${images[@]}"; do
|
||
for keyword in "${base_keywords[@]}"; do
|
||
if echo "$image" | grep -qi "$keyword"; then
|
||
filtered+=("$image")
|
||
break
|
||
fi
|
||
done
|
||
done
|
||
|
||
# 输出过滤后的镜像
|
||
printf '%s\n' "${filtered[@]}"
|
||
}
|
||
|
||
# 推送单个镜像
|
||
push_image() {
|
||
local source_image="$1"
|
||
local image_name
|
||
local image_tag
|
||
|
||
# 解析镜像名称和标签
|
||
if [[ "$source_image" =~ ^(.+):(.+)$ ]]; then
|
||
image_name="${BASH_REMATCH[1]}"
|
||
image_tag="${BASH_REMATCH[2]}"
|
||
else
|
||
image_name="$source_image"
|
||
image_tag="latest"
|
||
fi
|
||
|
||
# 移除仓库前缀(如果有)
|
||
image_name="${image_name##*/}"
|
||
|
||
# 构建目标镜像名称
|
||
local target_image="${HARBOR_REGISTRY}/${HARBOR_PROJECT}/${image_name}:${image_tag}"
|
||
|
||
log_info "推送镜像: ${source_image} -> ${target_image}"
|
||
|
||
# Tag 镜像
|
||
if docker tag "${source_image}" "${target_image}"; then
|
||
# 推送镜像
|
||
if docker push "${target_image}"; then
|
||
log_success "推送成功: ${target_image}"
|
||
return 0
|
||
else
|
||
log_error "推送失败: ${target_image}"
|
||
return 1
|
||
fi
|
||
else
|
||
log_error "Tag 失败: ${source_image}"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 推送所有镜像
|
||
push_all_images() {
|
||
local images
|
||
local total=0
|
||
local success=0
|
||
local failed=0
|
||
|
||
# 获取镜像列表
|
||
mapfile -t images < <(get_local_images | filter_base_images)
|
||
|
||
total=${#images[@]}
|
||
|
||
if [ "$total" -eq 0 ]; then
|
||
log_warning "没有找到需要推送的基础镜像"
|
||
return 0
|
||
fi
|
||
|
||
log_info "找到 ${total} 个基础镜像需要推送"
|
||
echo ""
|
||
|
||
# 显示镜像列表
|
||
log_info "镜像列表:"
|
||
printf '%s\n' "${images[@]}" | sed 's/^/ - /'
|
||
echo ""
|
||
|
||
# 询问确认
|
||
read -p "是否继续推送所有镜像?[y/N] " -n 1 -r
|
||
echo
|
||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||
log_warning "取消推送操作"
|
||
return 0
|
||
fi
|
||
|
||
# 推送所有镜像
|
||
for image in "${images[@]}"; do
|
||
if push_image "$image"; then
|
||
((success++))
|
||
else
|
||
((failed++))
|
||
fi
|
||
echo ""
|
||
done
|
||
|
||
# 输出统计信息
|
||
echo ""
|
||
log_info "推送统计:"
|
||
echo " 总计: ${total}"
|
||
echo " 成功: ${success}"
|
||
echo " 失败: ${failed}"
|
||
}
|
||
|
||
# 推送指定镜像
|
||
push_specific_images() {
|
||
local images=("$@")
|
||
|
||
log_info "推送指定的 ${#images[@]} 个镜像"
|
||
|
||
for image in "${images[@]}"; do
|
||
push_image "$image"
|
||
echo ""
|
||
done
|
||
}
|
||
|
||
# 显示使用说明
|
||
show_usage() {
|
||
cat <<EOF
|
||
使用方法:
|
||
$0 [OPTIONS] [IMAGE...]
|
||
|
||
选项:
|
||
-h, --help 显示此帮助信息
|
||
-a, --all 推送所有基础镜像(默认)
|
||
-l, --list 仅列出本地基础镜像,不推送
|
||
-p, --project NAME 指定 Harbor 项目(默认: library)
|
||
|
||
示例:
|
||
# 推送所有基础镜像
|
||
$0 --all
|
||
|
||
# 仅列出镜像
|
||
$0 --list
|
||
|
||
# 推送到指定项目
|
||
$0 --project myproject --all
|
||
|
||
# 推送指定镜像
|
||
$0 nginx:latest redis:7-alpine
|
||
|
||
EOF
|
||
}
|
||
|
||
# 主函数
|
||
main() {
|
||
local mode="all"
|
||
local specific_images=()
|
||
|
||
# 解析参数
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
-h|--help)
|
||
show_usage
|
||
exit 0
|
||
;;
|
||
-a|--all)
|
||
mode="all"
|
||
shift
|
||
;;
|
||
-l|--list)
|
||
mode="list"
|
||
shift
|
||
;;
|
||
-p|--project)
|
||
HARBOR_PROJECT="$2"
|
||
shift 2
|
||
;;
|
||
*)
|
||
specific_images+=("$1")
|
||
mode="specific"
|
||
shift
|
||
;;
|
||
esac
|
||
done
|
||
|
||
echo -e "${BLUE}======================================${NC}"
|
||
echo -e "${BLUE}Push Local Images to Harbor${NC}"
|
||
echo -e "${BLUE}======================================${NC}"
|
||
echo ""
|
||
echo "Harbor Registry: ${HARBOR_REGISTRY}"
|
||
echo "Harbor Project: ${HARBOR_PROJECT}"
|
||
echo ""
|
||
|
||
# 登录 Harbor
|
||
if ! harbor_login; then
|
||
exit 1
|
||
fi
|
||
echo ""
|
||
|
||
# 根据模式执行
|
||
case $mode in
|
||
all)
|
||
push_all_images
|
||
;;
|
||
list)
|
||
log_info "本地基础镜像列表:"
|
||
get_local_images | filter_base_images | sed 's/^/ - /'
|
||
;;
|
||
specific)
|
||
push_specific_images "${specific_images[@]}"
|
||
;;
|
||
esac
|
||
|
||
log_success "操作完成!"
|
||
}
|
||
|
||
# 执行主函数
|
||
main "$@"
|