feat(docker): 增强 Docker 安装脚本,支持多源切换和自动选择最佳源
This commit is contained in:
parent
8d7d0b2b12
commit
47daadc9bd
@ -94,66 +94,110 @@ install_basic_tools() {
|
||||
log_success "基础工具安装完成"
|
||||
}
|
||||
|
||||
# 安装 Docker (从国内源)
|
||||
# 安装 Docker (从国内源,支持多源切换)
|
||||
install_docker() {
|
||||
log_info "从国内源安装 Docker..."
|
||||
|
||||
# 卸载可能存在的旧版本
|
||||
apt remove -y docker docker-engine docker.io containerd runc 2>/dev/null || true
|
||||
|
||||
# 更新包索引
|
||||
apt update
|
||||
|
||||
# 安装必要的包
|
||||
apt install -y ca-certificates curl gnupg lsb-release
|
||||
|
||||
# 添加 Docker 的官方 GPG 密钥
|
||||
mkdir -p /etc/apt/keyrings
|
||||
curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
|
||||
# 设置仓库
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
# 更新包索引
|
||||
apt update
|
||||
|
||||
# 安装 Docker 最新版本
|
||||
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
# 配置 Docker 使用国内镜像
|
||||
mkdir -p /etc/docker
|
||||
cat > /etc/docker/daemon.json << 'EOF'
|
||||
log_info "从国内源安装 Docker (支持多源自动切换)..."
|
||||
|
||||
# 获取脚本所在目录
|
||||
local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
local docker_script="$script_dir/install_docker.sh"
|
||||
|
||||
# 检查是否存在独立的 Docker 安装脚本
|
||||
if [[ -f "$docker_script" ]]; then
|
||||
log_info "使用 install_docker.sh 脚本安装..."
|
||||
bash "$docker_script" --force
|
||||
else
|
||||
# 内联安装逻辑(多源支持)
|
||||
log_info "使用内置安装逻辑..."
|
||||
|
||||
# 定义多个 Docker 源
|
||||
local -A docker_sources=(
|
||||
["aliyun"]="https://mirrors.aliyun.com/docker-ce"
|
||||
["ustc"]="https://mirrors.ustc.edu.cn/docker-ce"
|
||||
["huawei"]="https://mirrors.huaweicloud.com/docker-ce"
|
||||
["163"]="https://mirrors.163.com/docker-ce"
|
||||
["tsinghua"]="https://mirrors.tuna.tsinghua.edu.cn/docker-ce"
|
||||
)
|
||||
local source_order=("aliyun" "ustc" "huawei" "163" "tsinghua")
|
||||
|
||||
# 卸载旧版本
|
||||
apt remove -y docker docker-engine docker.io containerd runc 2>/dev/null || true
|
||||
apt update
|
||||
apt install -y ca-certificates curl gnupg lsb-release
|
||||
|
||||
mkdir -p /etc/apt/keyrings
|
||||
local codename=$(lsb_release -cs)
|
||||
local arch=$(dpkg --print-architecture)
|
||||
local installed=false
|
||||
|
||||
for source_name in "${source_order[@]}"; do
|
||||
local source_url="${docker_sources[$source_name]}"
|
||||
log_info "尝试使用 $source_name 源: $source_url"
|
||||
|
||||
# 测试源
|
||||
if ! curl -sfL --connect-timeout 5 --max-time 10 "$source_url/linux/debian/gpg" -o /dev/null 2>/dev/null; then
|
||||
log_warning "$source_name 源不可用,跳过..."
|
||||
continue
|
||||
fi
|
||||
|
||||
# 配置源
|
||||
rm -f /etc/apt/keyrings/docker.gpg /etc/apt/sources.list.d/docker.list
|
||||
curl -fsSL "$source_url/linux/debian/gpg" | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
echo "deb [arch=$arch signed-by=/etc/apt/keyrings/docker.gpg] $source_url/linux/debian $codename stable" > /etc/apt/sources.list.d/docker.list
|
||||
|
||||
apt update
|
||||
|
||||
# 尝试安装
|
||||
set +e
|
||||
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 2>&1
|
||||
local result=$?
|
||||
set -e
|
||||
|
||||
if [[ $result -eq 0 ]]; then
|
||||
log_success "Docker 安装成功 (源: $source_name)"
|
||||
installed=true
|
||||
break
|
||||
else
|
||||
log_warning "从 $source_name 安装失败,尝试下一个源..."
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$installed" != "true" ]]; then
|
||||
log_error "Docker 安装失败,已尝试所有可用源"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 配置 Docker
|
||||
mkdir -p /etc/docker
|
||||
cat > /etc/docker/daemon.json << 'EOF'
|
||||
{
|
||||
"registry-mirrors": [
|
||||
"https://docker-proxy.syy.1msoft.cn",
|
||||
"https://registry.docker-cn.com",
|
||||
"https://docker.mirrors.ustc.edu.cn",
|
||||
"https://hub-mirror.c.163.com"
|
||||
"https://hub-mirror.c.163.com",
|
||||
"https://mirror.baidubce.com"
|
||||
],
|
||||
"log-driver": "json-file",
|
||||
"log-opts": {
|
||||
"max-size": "100m",
|
||||
"max-file": "3"
|
||||
}
|
||||
},
|
||||
"storage-driver": "overlay2"
|
||||
}
|
||||
EOF
|
||||
|
||||
# 启动 Docker 服务
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
|
||||
# 添加当前用户到 docker 组(如果用户存在)
|
||||
if id -u "$SUDO_USER" >/dev/null 2>&1; then
|
||||
usermod -aG docker "$SUDO_USER"
|
||||
log_info "已将用户 $SUDO_USER 添加到 docker 组,请重新登录以生效"
|
||||
fi
|
||||
|
||||
# 测试 Docker 安装
|
||||
if docker --version >/dev/null 2>&1; then
|
||||
log_success "Docker 安装成功,版本: $(docker --version)"
|
||||
log_info "Docker 镜像加速器已配置"
|
||||
else
|
||||
log_error "Docker 安装失败"
|
||||
exit 1
|
||||
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
|
||||
if id -u "$SUDO_USER" >/dev/null 2>&1; then
|
||||
usermod -aG docker "$SUDO_USER"
|
||||
log_info "已将用户 $SUDO_USER 添加到 docker 组,请重新登录以生效"
|
||||
fi
|
||||
|
||||
if docker --version >/dev/null 2>&1; then
|
||||
log_success "Docker 安装成功,版本: $(docker --version)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
# Debian 12 Docker 安装脚本 (使用国内源)
|
||||
# 从国内镜像源安装 Docker CE
|
||||
# 支持多源切换和自动选择最佳源
|
||||
|
||||
set -e
|
||||
|
||||
@ -29,6 +30,133 @@ log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 定义多个 Docker 源
|
||||
declare -A DOCKER_SOURCES=(
|
||||
["aliyun"]="https://mirrors.aliyun.com/docker-ce"
|
||||
["tsinghua"]="https://mirrors.tuna.tsinghua.edu.cn/docker-ce"
|
||||
["ustc"]="https://mirrors.ustc.edu.cn/docker-ce"
|
||||
["huawei"]="https://mirrors.huaweicloud.com/docker-ce"
|
||||
["163"]="https://mirrors.163.com/docker-ce"
|
||||
["azure"]="https://mirror.azure.cn/docker-ce"
|
||||
["official"]="https://download.docker.com"
|
||||
)
|
||||
|
||||
# 源优先级顺序
|
||||
DOCKER_SOURCE_ORDER=("aliyun" "ustc" "huawei" "163" "tsinghua" "azure" "official")
|
||||
|
||||
# 当前使用的源
|
||||
CURRENT_SOURCE=""
|
||||
CURRENT_SOURCE_URL=""
|
||||
|
||||
# 测试单个源的连接性
|
||||
test_source() {
|
||||
local source_name="$1"
|
||||
local source_url="${DOCKER_SOURCES[$source_name]}"
|
||||
local codename=$(lsb_release -cs)
|
||||
local arch=$(dpkg --print-architecture)
|
||||
|
||||
local test_url="${source_url}/linux/debian/dists/${codename}/stable/binary-${arch}/Packages"
|
||||
|
||||
# 测试连接
|
||||
local start_time=$(date +%s%N)
|
||||
if curl -sfL --connect-timeout 5 --max-time 15 "$test_url" -o /dev/null 2>/dev/null; then
|
||||
local end_time=$(date +%s%N)
|
||||
local time_diff=$(( (end_time - start_time) / 1000000 ))
|
||||
echo "$time_diff"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# 测试所有源并选择最佳
|
||||
select_best_source() {
|
||||
log_info "测试 Docker 源连接速度..."
|
||||
|
||||
local best_source=""
|
||||
local best_time=999999
|
||||
|
||||
for source_name in "${DOCKER_SOURCE_ORDER[@]}"; do
|
||||
local source_url="${DOCKER_SOURCES[$source_name]}"
|
||||
printf " %-12s %-50s " "$source_name" "$source_url"
|
||||
|
||||
if time_ms=$(test_source "$source_name"); then
|
||||
echo -e "${GREEN}✓${NC} ${time_ms}ms"
|
||||
if (( time_ms < best_time )); then
|
||||
best_time=$time_ms
|
||||
best_source=$source_name
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}✗${NC} 连接失败"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -n "$best_source" ]]; then
|
||||
log_success "选择最佳源: $best_source (${best_time}ms)"
|
||||
CURRENT_SOURCE="$best_source"
|
||||
CURRENT_SOURCE_URL="${DOCKER_SOURCES[$best_source]}"
|
||||
return 0
|
||||
else
|
||||
log_error "所有源均不可用"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 使用指定源
|
||||
use_source() {
|
||||
local source_name="$1"
|
||||
|
||||
if [[ -z "${DOCKER_SOURCES[$source_name]}" ]]; then
|
||||
log_error "未知的源: $source_name"
|
||||
log_info "可用源: ${!DOCKER_SOURCES[*]}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "测试指定源: $source_name"
|
||||
if test_source "$source_name" >/dev/null; then
|
||||
CURRENT_SOURCE="$source_name"
|
||||
CURRENT_SOURCE_URL="${DOCKER_SOURCES[$source_name]}"
|
||||
log_success "使用源: $source_name ($CURRENT_SOURCE_URL)"
|
||||
return 0
|
||||
else
|
||||
log_error "源 $source_name 不可用"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 尝试下一个源
|
||||
try_next_source() {
|
||||
local current="$CURRENT_SOURCE"
|
||||
local found_current=false
|
||||
|
||||
for source_name in "${DOCKER_SOURCE_ORDER[@]}"; do
|
||||
if [[ "$found_current" == "true" ]]; then
|
||||
if test_source "$source_name" >/dev/null; then
|
||||
CURRENT_SOURCE="$source_name"
|
||||
CURRENT_SOURCE_URL="${DOCKER_SOURCES[$source_name]}"
|
||||
log_info "切换到备用源: $source_name"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
if [[ "$source_name" == "$current" ]]; then
|
||||
found_current=true
|
||||
fi
|
||||
done
|
||||
|
||||
# 如果没有找到,从头开始尝试
|
||||
for source_name in "${DOCKER_SOURCE_ORDER[@]}"; do
|
||||
if [[ "$source_name" != "$current" ]]; then
|
||||
if test_source "$source_name" >/dev/null; then
|
||||
CURRENT_SOURCE="$source_name"
|
||||
CURRENT_SOURCE_URL="${DOCKER_SOURCES[$source_name]}"
|
||||
log_info "切换到备用源: $source_name"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# 检查系统要求
|
||||
check_system() {
|
||||
log_info "检查系统要求..."
|
||||
@ -99,31 +227,86 @@ install_dependencies() {
|
||||
|
||||
# 添加 Docker 仓库
|
||||
add_docker_repository() {
|
||||
log_info "添加 Docker 仓库 (使用清华大学镜像源)..."
|
||||
if [[ -z "$CURRENT_SOURCE_URL" ]]; then
|
||||
log_error "未选择 Docker 源"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "添加 Docker 仓库 (使用 $CURRENT_SOURCE 源)..."
|
||||
log_info "源地址: $CURRENT_SOURCE_URL"
|
||||
|
||||
# 创建密钥目录
|
||||
mkdir -p /etc/apt/keyrings
|
||||
|
||||
# 移除旧的密钥和仓库配置
|
||||
rm -f /etc/apt/keyrings/docker.gpg
|
||||
rm -f /etc/apt/sources.list.d/docker.list
|
||||
|
||||
# 下载并添加 GPG 密钥
|
||||
curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
log_info "下载 GPG 密钥..."
|
||||
if ! curl -fsSL "${CURRENT_SOURCE_URL}/linux/debian/gpg" | gpg --dearmor -o /etc/apt/keyrings/docker.gpg 2>/dev/null; then
|
||||
log_warning "从 $CURRENT_SOURCE 下载 GPG 密钥失败,尝试官方源..."
|
||||
curl -fsSL "https://download.docker.com/linux/debian/gpg" | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
fi
|
||||
|
||||
chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
|
||||
# 添加仓库
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
local arch=$(dpkg --print-architecture)
|
||||
local codename=$(lsb_release -cs)
|
||||
|
||||
echo "deb [arch=${arch} signed-by=/etc/apt/keyrings/docker.gpg] ${CURRENT_SOURCE_URL}/linux/debian ${codename} stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
log_success "Docker 仓库添加完成"
|
||||
log_success "Docker 仓库添加完成 (源: $CURRENT_SOURCE)"
|
||||
}
|
||||
|
||||
# 安装 Docker
|
||||
install_docker() {
|
||||
log_info "安装 Docker CE..."
|
||||
|
||||
local max_retries=3
|
||||
local retry_count=0
|
||||
|
||||
while (( retry_count < max_retries )); do
|
||||
# 更新包索引
|
||||
log_info "更新包索引..."
|
||||
if ! apt update 2>&1; then
|
||||
log_warning "apt update 失败"
|
||||
fi
|
||||
|
||||
# 更新包索引
|
||||
apt update
|
||||
|
||||
# 安装 Docker CE
|
||||
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
log_success "Docker CE 安装完成"
|
||||
# 尝试安装 Docker CE
|
||||
log_info "尝试从 $CURRENT_SOURCE 安装 Docker..."
|
||||
|
||||
# 使用 set +e 暂时禁用错误退出
|
||||
set +e
|
||||
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 2>&1
|
||||
local install_result=$?
|
||||
set -e
|
||||
|
||||
if [[ $install_result -eq 0 ]]; then
|
||||
log_success "Docker CE 安装完成 (源: $CURRENT_SOURCE)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
retry_count=$((retry_count + 1))
|
||||
log_warning "安装失败 (尝试 $retry_count/$max_retries)"
|
||||
|
||||
if (( retry_count < max_retries )); then
|
||||
log_info "尝试切换到其他源..."
|
||||
|
||||
if try_next_source; then
|
||||
# 重新配置仓库
|
||||
add_docker_repository
|
||||
else
|
||||
log_error "没有更多可用的源"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
log_error "Docker 安装失败,已尝试所有可用源"
|
||||
log_info "建议手动检查网络连接或稍后重试"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 配置 Docker
|
||||
@ -255,22 +438,48 @@ Docker 安装完成!
|
||||
EOF
|
||||
}
|
||||
|
||||
# 列出可用源
|
||||
list_sources() {
|
||||
echo "可用的 Docker 源:"
|
||||
echo "=========================================="
|
||||
for source_name in "${DOCKER_SOURCE_ORDER[@]}"; do
|
||||
printf " %-12s %s\n" "$source_name" "${DOCKER_SOURCES[$source_name]}"
|
||||
done
|
||||
echo ""
|
||||
echo "默认优先级: ${DOCKER_SOURCE_ORDER[*]}"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Debian 12 Docker 安装脚本
|
||||
|
||||
此脚本将从清华大学镜像源安装 Docker CE,并配置国内镜像加速器。
|
||||
此脚本支持多个国内镜像源,自动选择最佳源或手动指定源。
|
||||
|
||||
用法: $0 [选项]
|
||||
|
||||
选项:
|
||||
-h, --help 显示此帮助信息
|
||||
-f, --force 强制重新安装(不检查现有安装)
|
||||
-h, --help 显示此帮助信息
|
||||
-f, --force 强制重新安装(不检查现有安装)
|
||||
-s, --source NAME 指定使用的源 (aliyun, tsinghua, ustc, huawei, 163, azure, official)
|
||||
-t, --test 仅测试所有源的连接速度
|
||||
-l, --list 列出所有可用源
|
||||
|
||||
可用源:
|
||||
aliyun 阿里云镜像 (推荐)
|
||||
tsinghua 清华大学镜像
|
||||
ustc 中科大镜像
|
||||
huawei 华为云镜像
|
||||
163 网易镜像
|
||||
azure 微软 Azure 镜像
|
||||
official Docker 官方源
|
||||
|
||||
示例:
|
||||
$0 # 正常安装
|
||||
$0 --force # 强制重新安装
|
||||
$0 # 自动选择最佳源安装
|
||||
$0 -s aliyun # 使用阿里云源安装
|
||||
$0 -s ustc --force # 使用中科大源强制重装
|
||||
$0 --test # 测试所有源速度
|
||||
$0 --list # 列出所有可用源
|
||||
|
||||
EOF
|
||||
}
|
||||
@ -278,6 +487,8 @@ EOF
|
||||
# 主函数
|
||||
main() {
|
||||
local force_install=false
|
||||
local specified_source=""
|
||||
local test_only=false
|
||||
|
||||
# 解析参数
|
||||
while [[ $# -gt 0 ]]; do
|
||||
@ -290,6 +501,18 @@ main() {
|
||||
force_install=true
|
||||
shift
|
||||
;;
|
||||
-s|--source)
|
||||
specified_source="$2"
|
||||
shift 2
|
||||
;;
|
||||
-t|--test)
|
||||
test_only=true
|
||||
shift
|
||||
;;
|
||||
-l|--list)
|
||||
list_sources
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log_error "未知选项: $1"
|
||||
show_help
|
||||
@ -304,6 +527,12 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 仅测试模式
|
||||
if [[ "$test_only" == true ]]; then
|
||||
select_best_source
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 检查是否已安装
|
||||
if command -v docker &> /dev/null && [[ "$force_install" != true ]]; then
|
||||
log_warning "Docker 已经安装。如需重新安装,请使用 --force 选项。"
|
||||
@ -315,6 +544,19 @@ main() {
|
||||
echo
|
||||
|
||||
check_system
|
||||
|
||||
# 选择源
|
||||
if [[ -n "$specified_source" ]]; then
|
||||
if ! use_source "$specified_source"; then
|
||||
log_warning "指定源不可用,自动选择最佳源..."
|
||||
select_best_source || exit 1
|
||||
fi
|
||||
else
|
||||
select_best_source || exit 1
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
uninstall_old_versions
|
||||
install_dependencies
|
||||
add_docker_repository
|
||||
@ -325,7 +567,7 @@ main() {
|
||||
test_installation
|
||||
|
||||
echo
|
||||
log_success "Docker 安装完成!"
|
||||
log_success "Docker 安装完成!(使用源: $CURRENT_SOURCE)"
|
||||
}
|
||||
|
||||
# 执行主函数
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user