Files
macos-tools/harbor/pull-and-cache.sh
2025-12-24 13:42:39 +08:00

268 lines
6.2 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
###############################################################################
# Harbor 按需拉取并缓存镜像脚本
# 解决 Proxy Cache 不工作的问题,使用手动拉取+推送方式
###############################################################################
set -eo pipefail
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[✓]${NC} $1"
}
log_error() {
echo -e "${RED}[✗]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[!]${NC} $1"
}
# Harbor 配置
HARBOR_HOST="${HARBOR_HOST:-harbor.omniverseai.net}"
HARBOR_PROJECT="${HARBOR_PROJECT:-library}"
PLATFORM="${PLATFORM:-linux/arm64}"
# 显示帮助
show_help() {
cat << EOF
Harbor 按需拉取并缓存镜像脚本
用法:
$0 IMAGE[:TAG] 拉取并缓存单个镜像
$0 -f FILE 从文件批量拉取镜像
$0 -l 列出已缓存的镜像
参数:
IMAGE[:TAG] 镜像名称和标签(默认标签: latest)
-f FILE 镜像列表文件(每行一个镜像)
-l 列出 Harbor 中已缓存的镜像
-h, --help 显示帮助信息
环境变量:
HARBOR_HOST Harbor 地址(默认: harbor.omniverseai.net)
HARBOR_PROJECT Harbor 项目名(默认: library)
PLATFORM 镜像平台(默认: linux/arm64)
示例:
# 拉取单个镜像
$0 nginx:alpine
# 拉取多个镜像
$0 redis:alpine
$0 postgres:16-alpine
$0 mysql:8.0
# 从文件批量拉取
echo "nginx:alpine" > images.txt
echo "redis:alpine" >> images.txt
$0 -f images.txt
# 列出已缓存镜像
$0 -l
工作流程:
1. 从 Docker Hub 拉取 ARM64 镜像
2. 标记为 Harbor 路径
3. 推送到 Harbor
4. 验证可用性
EOF
}
# 拉取并缓存单个镜像
pull_and_cache() {
local image=$1
# 添加默认标签
if [[ ! "$image" =~ ":" ]]; then
image="${image}:latest"
fi
log_info "=== 拉取并缓存镜像: $image ==="
echo ""
local harbor_image="${HARBOR_HOST}/${HARBOR_PROJECT}/${image}"
# 1. 从 Docker Hub 拉取
log_info "[1/4] 从 Docker Hub 拉取 ARM64 镜像..."
if docker pull --platform "$PLATFORM" "$image"; then
log_success "拉取成功: $image"
else
log_error "拉取失败: $image"
return 1
fi
echo ""
# 2. 标记为 Harbor 镜像
log_info "[2/4] 标记为 Harbor 镜像..."
if docker tag "$image" "$harbor_image"; then
log_success "标记成功: $harbor_image"
else
log_error "标记失败"
return 1
fi
echo ""
# 3. 推送到 Harbor
log_info "[3/4] 推送到 Harbor..."
if docker push "$harbor_image"; then
log_success "推送成功"
else
log_error "推送失败"
return 1
fi
echo ""
# 4. 验证镜像架构
log_info "[4/4] 验证镜像架构..."
local arch=$(docker inspect "$harbor_image" --format '{{.Architecture}}' 2>/dev/null || echo "unknown")
if [ "$arch" = "arm64" ]; then
log_success "架构验证通过: $arch"
else
log_warning "架构: $arch (预期: arm64)"
fi
echo ""
log_success "✅ 镜像已成功缓存到 Harbor!"
echo ""
echo " 原始镜像: $image"
echo " Harbor 路径: $harbor_image"
echo " 架构: $arch"
echo ""
echo "在 Kubernetes 中使用:"
echo " image: $harbor_image"
echo ""
return 0
}
# 从文件批量拉取
pull_from_file() {
local file=$1
if [ ! -f "$file" ]; then
log_error "文件不存在: $file"
return 1
fi
log_info "从文件批量拉取: $file"
echo ""
local total=0
local success=0
local failed=0
while IFS= read -r line; do
# 跳过空行和注释
[[ -z "$line" ]] && continue
[[ "$line" =~ ^#.* ]] && continue
total=$((total + 1))
if pull_and_cache "$line"; then
success=$((success + 1))
else
failed=$((failed + 1))
fi
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
done < "$file"
log_info "批量拉取完成"
echo " 总数: $total"
echo " 成功: $success"
echo " 失败: $failed"
}
# 列出已缓存的镜像
list_cached() {
log_info "查询 Harbor 中已缓存的镜像..."
echo ""
local response=$(curl -s -k -u "admin:admin123" \
"http://192.168.1.83:8080/api/v2.0/projects/${HARBOR_PROJECT}/repositories")
echo "$response" | python3 -c "
import sys, json
try:
repos = json.load(sys.stdin)
print(f'Harbor {\"${HARBOR_PROJECT}\"} 项目中的镜像: {len(repos)} 个\n')
print('─' * 80)
for r in repos:
name = r['name'].replace('${HARBOR_PROJECT}/', '')
artifacts = r.get('artifact_count', 0)
print(f\" {name:<50} (Artifacts: {artifacts})\")
print('─' * 80)
print(f'\n使用方式: docker pull ${HARBOR_HOST}/${HARBOR_PROJECT}/IMAGE:TAG')
except Exception as e:
print(f'查询失败: {e}')
"
}
# 主函数
main() {
# 检查 Docker 是否运行
if ! docker info > /dev/null 2>&1; then
log_error "Docker 未运行,请先启动 Docker"
exit 1
fi
# 检查是否已登录 Harbor
if ! docker login "$HARBOR_HOST" -u admin -p admin123 > /dev/null 2>&1; then
log_warning "Harbor 登录失败,尝试继续..."
fi
# 解析参数
case "${1:-}" in
-h|--help|help)
show_help
exit 0
;;
-l|--list|list)
list_cached
exit 0
;;
-f|--file)
if [ -z "${2:-}" ]; then
log_error "请指定镜像列表文件"
echo "用法: $0 -f FILE"
exit 1
fi
pull_from_file "$2"
exit $?
;;
"")
log_error "请指定镜像名称"
echo ""
show_help
exit 1
;;
*)
pull_and_cache "$1"
exit $?
;;
esac
}
# 执行主程序
main "$@"