追加Docker镜像加速检测功能的新版Deploy.sh
This commit is contained in:
@@ -24,9 +24,28 @@ DEFAULT_DEPLOY_DIR="/opt/frpc-console"
|
||||
IMAGE_NAME="frpc-console"
|
||||
KEEP_IMAGES=3
|
||||
|
||||
# ---------- 状态变量 ----------
|
||||
# ---------- 镜像加速配置 ----------
|
||||
DEFAULT_MIRRORS=(
|
||||
"https://docker.1panel.live"
|
||||
"https://docker.1panel.dev"
|
||||
"https://docker.1ms.run"
|
||||
)
|
||||
DAEMON_JSON="/etc/docker/daemon.json"
|
||||
MIRROR_CHECK_TIMEOUT=5
|
||||
|
||||
# ---------- 镜像加速状态变量 ----------
|
||||
MIRROR_STATUS="" # no_config | has_mirrors | default_unavailable
|
||||
NEED_RESTART=false # 是否需要重启 Docker
|
||||
NEED_REORDER=false # 是否需要重排已有镜像源
|
||||
HAS_REGISTRY_MIRRORS_KEY=false # daemon.json 中是否存在 registry-mirrors 字段
|
||||
AVAILABLE_MIRRORS=() # 可用的默认地址
|
||||
USER_MIRRORS_AVAILABLE=() # 用户配置中可用的地址
|
||||
USER_MIRRORS_UNAVAILABLE=() # 用户配置中不可用的地址
|
||||
|
||||
# ---------- 其他状态变量 ----------
|
||||
OS=""; OS_VERSION=""; ARCH=""
|
||||
HAS_GIT=false; HAS_CURL=false; HAS_WGET=false; HAS_DOCKER=false
|
||||
HAS_JQ=false
|
||||
NEED_INSTALL_GIT=false; NEED_INSTALL_CURL=false; NEED_INSTALL_WGET=false
|
||||
PORT=${DEFAULT_PORT}
|
||||
DEPLOY_DIR=${DEFAULT_DEPLOY_DIR}
|
||||
@@ -36,6 +55,7 @@ SKIP_CONFIRM=false; CHECK_ONLY=false; DRY_RUN=false
|
||||
CHANNEL=""; BRANCH=""; TARGET_VERSION=""; IMAGE_TAG=""
|
||||
CURRENT_VERSION=""
|
||||
|
||||
# ---------- 打印函数 ----------
|
||||
print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
print_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
||||
print_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; }
|
||||
@@ -65,6 +85,7 @@ parse_args() {
|
||||
done
|
||||
}
|
||||
|
||||
# ---------- 权限检测 ----------
|
||||
check_root() {
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
print_error "请使用 root 权限运行此脚本"
|
||||
@@ -73,6 +94,7 @@ check_root() {
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------- 系统检测 ----------
|
||||
detect_os() {
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
@@ -96,11 +118,13 @@ detect_arch() {
|
||||
esac
|
||||
}
|
||||
|
||||
# ---------- 工具检测 ----------
|
||||
check_tools() {
|
||||
command -v git &> /dev/null && HAS_GIT=true || NEED_INSTALL_GIT=true
|
||||
command -v curl &> /dev/null && HAS_CURL=true || NEED_INSTALL_CURL=true
|
||||
command -v wget &> /dev/null && HAS_WGET=true || NEED_INSTALL_WGET=true
|
||||
command -v docker &> /dev/null && HAS_DOCKER=true
|
||||
command -v jq &> /dev/null && HAS_JQ=true || HAS_JQ=false
|
||||
}
|
||||
|
||||
check_container() {
|
||||
@@ -112,6 +136,328 @@ check_container() {
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------- 镜像加速:连通性检测 ----------
|
||||
check_mirror_available() {
|
||||
local url="$1"
|
||||
local http_code
|
||||
http_code=$(curl -s --max-time "$MIRROR_CHECK_TIMEOUT" -o /dev/null -w "%{http_code}" \
|
||||
"${url}/v2/" 2>/dev/null)
|
||||
if [[ "$http_code" =~ ^2[0-9][0-9]$ ]] || [ "$http_code" = "401" ] || [ "$http_code" = "403" ]; then
|
||||
# 2xx 表示成功,401/403 表示需要认证但服务可达(也是可用的)
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# ---------- 镜像加速:安装 jq ----------
|
||||
install_jq() {
|
||||
print_info "尝试安装 jq..."
|
||||
case $OS in
|
||||
opensuse*|suse*|opensuse-tumbleweed|opensuse-slowroll|opensuse-leap)
|
||||
zypper install -y jq 2>/dev/null || true
|
||||
;;
|
||||
ubuntu|debian|linuxmint)
|
||||
apt update -qq 2>/dev/null && apt install -y jq 2>/dev/null || true
|
||||
;;
|
||||
centos|rhel|fedora|rocky|almalinux)
|
||||
yum install -y jq 2>/dev/null || true
|
||||
;;
|
||||
alpine)
|
||||
apk add jq 2>/dev/null || true
|
||||
;;
|
||||
arch|manjaro|endeavouros)
|
||||
pacman -S --needed --noconfirm jq 2>/dev/null || true
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
command -v jq &> /dev/null && HAS_JQ=true || HAS_JQ=false
|
||||
if [ "$HAS_JQ" = true ]; then
|
||||
print_success "jq 安装成功"
|
||||
return 0
|
||||
else
|
||||
print_warn "jq 安装失败,将使用 sed 模式(功能受限)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------- 镜像加速:检测阶段 ----------
|
||||
check_docker_mirrors() {
|
||||
print_step "检测 Docker 镜像源配置..."
|
||||
|
||||
# 1. 检测三个默认地址的连通性
|
||||
print_info "检测默认镜像源连通性 (超时 ${MIRROR_CHECK_TIMEOUT}s)..."
|
||||
for mirror in "${DEFAULT_MIRRORS[@]}"; do
|
||||
if check_mirror_available "$mirror"; then
|
||||
AVAILABLE_MIRRORS+=("$mirror")
|
||||
print_info " ✅ $mirror 可用"
|
||||
else
|
||||
print_info " ❌ $mirror 不可用"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#AVAILABLE_MIRRORS[@]} -eq 0 ]; then
|
||||
MIRROR_STATUS="default_unavailable"
|
||||
print_warn "所有默认镜像源均不可用,将跳过镜像加速配置"
|
||||
print_warn "如果 Docker 构建失败,请检查网络或手动配置镜像源"
|
||||
return 0
|
||||
fi
|
||||
|
||||
print_success "找到 ${#AVAILABLE_MIRRORS[@]} 个可用默认镜像源"
|
||||
|
||||
# 2. 检查 daemon.json
|
||||
if [ ! -f "$DAEMON_JSON" ]; then
|
||||
MIRROR_STATUS="no_config"
|
||||
HAS_REGISTRY_MIRRORS_KEY=false
|
||||
print_info "daemon.json 不存在,将创建新配置"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 3. 检测 jq 是否可解析
|
||||
if ! jq -e '.' "$DAEMON_JSON" >/dev/null 2>&1 2>/dev/null; then
|
||||
print_warn "daemon.json 格式不标准,将备份并重建"
|
||||
local backup_path="${DAEMON_JSON}.bak.$(date +%Y%m%d-%H%M%S)"
|
||||
cp "$DAEMON_JSON" "$backup_path"
|
||||
print_info "已备份至: $backup_path"
|
||||
echo '{}' > "$DAEMON_JSON"
|
||||
print_warn "已重建 daemon.json,请确认是否需要将其他自定义配置迁回"
|
||||
MIRROR_STATUS="no_config"
|
||||
HAS_REGISTRY_MIRRORS_KEY=false
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 4. 检查是否存在 registry-mirrors 字段
|
||||
local has_key
|
||||
has_key=$(jq -e 'has("registry-mirrors")' "$DAEMON_JSON" 2>/dev/null)
|
||||
if [ "$has_key" != "true" ]; then
|
||||
HAS_REGISTRY_MIRRORS_KEY=false
|
||||
MIRROR_STATUS="has_mirrors"
|
||||
print_info "daemon.json 中无 registry-mirrors 字段,将仅插入该字段(保留其他配置)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
HAS_REGISTRY_MIRRORS_KEY=true
|
||||
|
||||
# 5. 读取 registry-mirrors 数组
|
||||
local mirror_list
|
||||
mirror_list=$(jq -r '."registry-mirrors" // [] | .[]' "$DAEMON_JSON" 2>/dev/null)
|
||||
if [ -z "$mirror_list" ]; then
|
||||
MIRROR_STATUS="has_mirrors"
|
||||
print_info "registry-mirrors 为空数组,将写入默认地址"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 6. 检测用户配置中每个地址的连通性
|
||||
print_info "检测用户配置的镜像源连通性..."
|
||||
USER_MIRRORS_AVAILABLE=()
|
||||
USER_MIRRORS_UNAVAILABLE=()
|
||||
|
||||
while IFS= read -r mirror; do
|
||||
if [ -n "$mirror" ]; then
|
||||
if check_mirror_available "$mirror"; then
|
||||
USER_MIRRORS_AVAILABLE+=("$mirror")
|
||||
print_info " ✅ $mirror (用户配置) 可用"
|
||||
else
|
||||
USER_MIRRORS_UNAVAILABLE+=("$mirror")
|
||||
print_info " ❌ $mirror (用户配置) 不可用"
|
||||
fi
|
||||
fi
|
||||
done <<< "$mirror_list"
|
||||
|
||||
MIRROR_STATUS="has_mirrors"
|
||||
|
||||
# 7. 判断是否需要重排
|
||||
if [ ${#USER_MIRRORS_AVAILABLE[@]} -gt 0 ]; then
|
||||
# 检查可用地址是否已经全部排在不可用地址前面
|
||||
NEED_REORDER=false
|
||||
local seen_unavailable=false
|
||||
for mirror in "${USER_MIRRORS_AVAILABLE[@]}" "${USER_MIRRORS_UNAVAILABLE[@]}"; do
|
||||
# 遍历原始顺序:在 USER_MIRRORS_AVAILABLE 和 USER_MIRRORS_UNAVAILABLE 的拼接中,
|
||||
# 如果先遇到不可用,再遇到可用,说明需要重排
|
||||
# 但我们这里无法直接还原原始顺序,用另一个方法:检查原始列表中是否存在可用在不可用之后
|
||||
# 更简单的方法:如果存在任何一个不可用在可用之前
|
||||
# 用原始列表检测
|
||||
local raw_list
|
||||
raw_list=$(jq -r '."registry-mirrors" // [] | .[]' "$DAEMON_JSON" 2>/dev/null)
|
||||
local raw_available=()
|
||||
local raw_unavailable=()
|
||||
while IFS= read -r m; do
|
||||
if [ -n "$m" ]; then
|
||||
local found=false
|
||||
for a in "${USER_MIRRORS_AVAILABLE[@]}"; do
|
||||
if [ "$a" = "$m" ]; then
|
||||
raw_available+=("$m")
|
||||
found=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "$found" = false ]; then
|
||||
raw_unavailable+=("$m")
|
||||
fi
|
||||
fi
|
||||
done <<< "$raw_list"
|
||||
|
||||
# 检查原始列表中,是否有不可用地址出现在可用地址之前
|
||||
local seen_avail=false
|
||||
for m in "${raw_available[@]}" "${raw_unavailable[@]}"; do
|
||||
# 这里只检查原始顺序
|
||||
true
|
||||
done
|
||||
|
||||
# 更准确的方法:遍历原始列表,记录是否见过不可用
|
||||
local seen_unavail=false
|
||||
local need_reorder=false
|
||||
while IFS= read -r m; do
|
||||
if [ -n "$m" ]; then
|
||||
local is_avail=false
|
||||
for a in "${USER_MIRRORS_AVAILABLE[@]}"; do
|
||||
if [ "$a" = "$m" ]; then
|
||||
is_avail=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "$is_avail" = true ] && [ "$seen_unavail" = true ]; then
|
||||
need_reorder=true
|
||||
break
|
||||
fi
|
||||
if [ "$is_avail" = false ]; then
|
||||
seen_unavail=true
|
||||
fi
|
||||
fi
|
||||
done <<< "$raw_list"
|
||||
NEED_REORDER=$need_reorder
|
||||
done
|
||||
|
||||
if [ "$NEED_REORDER" = true ]; then
|
||||
print_info "检测到可用镜像源排在不可用镜像源之后,需要重排"
|
||||
else
|
||||
print_info "用户镜像源配置正常,无需调整"
|
||||
fi
|
||||
elif [ ${#USER_MIRRORS_UNAVAILABLE[@]} -gt 0 ] && [ ${#AVAILABLE_MIRRORS[@]} -gt 0 ]; then
|
||||
# 用户配置全部不可用,但有可用的默认地址
|
||||
NEED_REORDER=true
|
||||
print_info "用户配置全部不可用,将插入可用默认地址"
|
||||
fi
|
||||
|
||||
print_success "镜像源检测完成"
|
||||
}
|
||||
|
||||
# ---------- 镜像加速:配置执行阶段 ----------
|
||||
configure_docker_mirrors() {
|
||||
print_step "配置 Docker 镜像源..."
|
||||
|
||||
if [ "$MIRROR_STATUS" = "default_unavailable" ]; then
|
||||
print_warn "无可用默认镜像源,跳过配置"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ ${#AVAILABLE_MIRRORS[@]} -eq 0 ]; then
|
||||
print_warn "无可用的默认镜像源,跳过配置"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 确保 jq 可用
|
||||
if [ "$HAS_JQ" = false ]; then
|
||||
print_warn "jq 未安装,尝试安装..."
|
||||
if ! install_jq; then
|
||||
print_error "jq 安装失败,无法配置镜像源"
|
||||
print_error "请手动配置 /etc/docker/daemon.json 中的 registry-mirrors"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
local new_mirrors=()
|
||||
local need_write=false
|
||||
local need_restart=false
|
||||
|
||||
# 情况判断
|
||||
if [ "$HAS_REGISTRY_MIRRORS_KEY" = false ]; then
|
||||
# 不存在 registry-mirrors 字段,直接插入
|
||||
new_mirrors=("${AVAILABLE_MIRRORS[@]}")
|
||||
need_write=true
|
||||
need_restart=true
|
||||
print_info "插入 registry-mirrors 字段: ${AVAILABLE_MIRRORS[*]}"
|
||||
elif [ ${#USER_MIRRORS_AVAILABLE[@]} -eq 0 ] && [ ${#USER_MIRRORS_UNAVAILABLE[@]} -eq 0 ]; then
|
||||
# 空数组,直接写入
|
||||
new_mirrors=("${AVAILABLE_MIRRORS[@]}")
|
||||
need_write=true
|
||||
need_restart=true
|
||||
print_info "写入 registry-mirrors: ${AVAILABLE_MIRRORS[*]}"
|
||||
elif [ ${#USER_MIRRORS_AVAILABLE[@]} -gt 0 ]; then
|
||||
if [ "$NEED_REORDER" = true ]; then
|
||||
# 重排:可用地址在前 + 不可用地址在后(仅限用户配置中不可用的)
|
||||
new_mirrors=("${USER_MIRRORS_AVAILABLE[@]}" "${USER_MIRRORS_UNAVAILABLE[@]}")
|
||||
need_write=true
|
||||
need_restart=true
|
||||
print_info "重排镜像源: 可用前置"
|
||||
else
|
||||
print_info "镜像源配置正常,无需修改"
|
||||
return 0
|
||||
fi
|
||||
elif [ ${#USER_MIRRORS_AVAILABLE[@]} -eq 0 ] && [ ${#USER_MIRRORS_UNAVAILABLE[@]} -gt 0 ]; then
|
||||
# 用户配置全部不可用,插入可用默认地址到最前面
|
||||
new_mirrors=("${AVAILABLE_MIRRORS[@]}" "${USER_MIRRORS_UNAVAILABLE[@]}")
|
||||
need_write=true
|
||||
need_restart=true
|
||||
print_info "插入可用默认镜像源到最前面: ${AVAILABLE_MIRRORS[*]}"
|
||||
else
|
||||
print_info "无需修改镜像源配置"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$need_write" = false ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 检查是否需要重启 Docker(交互模式确认)
|
||||
if [ "$need_restart" = true ] && [ "$SKIP_CONFIRM" != true ]; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠ 修改 Docker 镜像源配置需要重启 Docker 服务。${NC}"
|
||||
echo -e "${YELLOW} 重启可能影响其他正在运行的容器。${NC}"
|
||||
read -p "确认继续? [y/N]: " confirm </dev/tty
|
||||
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||
print_info "已取消配置修改"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# 备份 daemon.json(如果存在且可读)
|
||||
if [ -f "$DAEMON_JSON" ]; then
|
||||
local backup_path="${DAEMON_JSON}.bak.$(date +%Y%m%d-%H%M%S)"
|
||||
cp "$DAEMON_JSON" "$backup_path"
|
||||
print_info "已备份: $backup_path"
|
||||
fi
|
||||
|
||||
# 写入新配置
|
||||
local json_mirrors
|
||||
json_mirrors=$(printf '%s\n' "${new_mirrors[@]}" | jq -R . | jq -s .)
|
||||
|
||||
if ! jq --argjson mirrors "$json_mirrors" '."registry-mirrors" = $mirrors' \
|
||||
"$DAEMON_JSON" > "${DAEMON_JSON}.tmp" 2>/dev/null; then
|
||||
print_error "写入 daemon.json 失败"
|
||||
return 1
|
||||
fi
|
||||
|
||||
mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON"
|
||||
print_success "daemon.json 已更新"
|
||||
|
||||
# 重启 Docker
|
||||
if [ "$need_restart" = true ]; then
|
||||
print_step "重启 Docker 服务..."
|
||||
if systemctl restart docker 2>/dev/null; then
|
||||
print_success "Docker 重启完成"
|
||||
sleep 2
|
||||
else
|
||||
print_error "Docker 重启失败,请手动重启后重新运行脚本"
|
||||
print_info "手动重启命令: systemctl restart docker"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
print_success "镜像源配置完成"
|
||||
}
|
||||
|
||||
# ---------- 版本管理 ----------
|
||||
read_version_from_remote() {
|
||||
local branch="$1"
|
||||
@@ -227,6 +573,22 @@ print_environment_summary() {
|
||||
print_error "Docker 未安装,请先安装 Docker"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
echo " ${CYAN}镜像源状态:${NC}"
|
||||
if [ ${#AVAILABLE_MIRRORS[@]} -gt 0 ]; then
|
||||
echo " 可用默认镜像源: ${AVAILABLE_MIRRORS[*]}"
|
||||
else
|
||||
echo " 可用默认镜像源: 无"
|
||||
fi
|
||||
if [ ${#USER_MIRRORS_AVAILABLE[@]} -gt 0 ]; then
|
||||
echo " 用户配置可用: ${USER_MIRRORS_AVAILABLE[*]}"
|
||||
elif [ ${#USER_MIRRORS_UNAVAILABLE[@]} -gt 0 ]; then
|
||||
echo " 用户配置: ${#USER_MIRRORS_UNAVAILABLE[@]} 个地址均不可用"
|
||||
elif [ "$HAS_REGISTRY_MIRRORS_KEY" = false ]; then
|
||||
echo " 用户配置: 无 registry-mirrors"
|
||||
else
|
||||
echo " 用户配置: 无"
|
||||
fi
|
||||
if [ "$CONTAINER_EXISTS" = true ]; then
|
||||
echo ""
|
||||
echo " ${CYAN}容器状态:${NC}"
|
||||
@@ -251,6 +613,11 @@ generate_plan() {
|
||||
[ "$NEED_INSTALL_WGET" = true ] && pkgs="${pkgs} wget"
|
||||
PLAN="${PLAN} • 安装必要工具:${pkgs}\n"
|
||||
fi
|
||||
if [ "$MIRROR_STATUS" != "default_unavailable" ] && [ ${#AVAILABLE_MIRRORS[@]} -gt 0 ]; then
|
||||
if [ "$HAS_REGISTRY_MIRRORS_KEY" = false ] || [ ${#USER_MIRRORS_AVAILABLE[@]} -eq 0 -a ${#USER_MIRRORS_UNAVAILABLE[@]} -eq 0 ] || [ "$NEED_REORDER" = true ]; then
|
||||
PLAN="${PLAN} • 配置 Docker 镜像加速\n"
|
||||
fi
|
||||
fi
|
||||
PLAN="${PLAN} • 拉取 frpc-console 源码 (${BRANCH} 分支)\n"
|
||||
PLAN="${PLAN} • 构建 Docker 镜像: ${IMAGE_NAME}:${IMAGE_TAG}\n"
|
||||
PLAN="${PLAN} • 目标版本: ${TARGET_VERSION}\n"
|
||||
@@ -384,6 +751,14 @@ do_deploy() {
|
||||
mkdir -p bin static
|
||||
print_success "代码拉取完成 (分支: ${BRANCH})"
|
||||
|
||||
# ============================================================
|
||||
# 镜像加速配置:拉取代码之后、docker build 之前执行
|
||||
# ============================================================
|
||||
if ! configure_docker_mirrors; then
|
||||
print_error "镜像源配置失败,请检查后重试"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ----- 停止旧容器 -----
|
||||
if [ "$CONTAINER_EXISTS" = true ]; then
|
||||
print_step "停止旧容器..."
|
||||
@@ -594,6 +969,9 @@ main() {
|
||||
check_tools
|
||||
check_container
|
||||
|
||||
# ---------- 镜像源检测(拉取代码前,只检测不修改) ----------
|
||||
check_docker_mirrors
|
||||
|
||||
select_channel
|
||||
generate_target_version "$CHANNEL" "$BRANCH"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user