512 lines
14 KiB
Bash
Executable File
512 lines
14 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Docker 镜像加速器快速设置脚本
|
|
# 支持多种国内镜像源配置
|
|
|
|
set -e
|
|
|
|
# 颜色定义
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
PURPLE='\033[0;35m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
# 日志函数
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
log_title() {
|
|
echo -e "${PURPLE}[DOCKER MIRRORS]${NC} $1"
|
|
}
|
|
|
|
# 镜像源配置
|
|
MIRRORS_aliyun="https://registry.cn-hangzhou.aliyuncs.com"
|
|
MIRRORS_tencent="https://mirror.ccs.tencentyun.com"
|
|
MIRRORS_huawei="https://mirror-1.trustie.net"
|
|
MIRRORS_netease="https://hub-mirror.c.163.com"
|
|
MIRRORS_ustc="https://docker.mirrors.ustc.edu.cn"
|
|
MIRRORS_docker_cn="https://registry.docker-cn.com"
|
|
MIRRORS_baidu="https://mirror.baidubce.com"
|
|
MIRRORS_tsinghua="https://mirrors.tuna.tsinghua.edu.cn"
|
|
|
|
# 镜像源名称数组
|
|
MIRROR_NAMES=("aliyun" "tencent" "huawei" "netease" "ustc" "docker_cn" "baidu" "tsinghua")
|
|
|
|
# 配置文件路径
|
|
DOCKER_CONFIG="/etc/docker/daemon.json"
|
|
DOCKER_CONFIG_BACKUP="/etc/docker/daemon.json.backup.$(date +%Y%m%d_%H%M%S)"
|
|
|
|
# 检查 Docker 是否安装
|
|
check_docker() {
|
|
if ! command -v docker &> /dev/null; then
|
|
log_error "Docker 未安装,请先安装 Docker"
|
|
echo "运行以下命令安装 Docker:"
|
|
echo " sudo ./scripts/packages/install_docker.sh"
|
|
exit 1
|
|
fi
|
|
|
|
if ! systemctl is-active --quiet docker; then
|
|
log_warning "Docker 服务未运行,正在启动..."
|
|
systemctl start docker
|
|
sleep 2
|
|
if ! systemctl is-active --quiet docker; then
|
|
log_error "无法启动 Docker 服务"
|
|
exit 1
|
|
fi
|
|
log_success "Docker 服务已启动"
|
|
fi
|
|
}
|
|
|
|
# 检查 Docker 配置文件
|
|
check_config() {
|
|
if [[ ! -f "$DOCKER_CONFIG" ]]; then
|
|
log_info "创建 Docker 配置文件..."
|
|
mkdir -p /etc/docker
|
|
echo '{}' > "$DOCKER_CONFIG"
|
|
fi
|
|
}
|
|
|
|
# 备份当前配置
|
|
backup_config() {
|
|
if [[ -f "$DOCKER_CONFIG" ]]; then
|
|
cp "$DOCKER_CONFIG" "$DOCKER_CONFIG_BACKUP"
|
|
log_info "配置已备份到: $DOCKER_CONFIG_BACKUP"
|
|
fi
|
|
}
|
|
|
|
# 获取当前配置
|
|
get_current_config() {
|
|
if [[ -f "$DOCKER_CONFIG" ]]; then
|
|
cat "$DOCKER_CONFIG"
|
|
else
|
|
echo "{}"
|
|
fi
|
|
}
|
|
|
|
# 更新配置文件
|
|
update_config() {
|
|
local new_config="$1"
|
|
echo "$new_config" > "$DOCKER_CONFIG"
|
|
log_info "Docker 配置已更新"
|
|
}
|
|
|
|
# 重启 Docker 服务
|
|
restart_docker() {
|
|
log_info "重启 Docker 服务..."
|
|
systemctl daemon-reload
|
|
systemctl restart docker
|
|
|
|
# 等待服务启动
|
|
sleep 3
|
|
|
|
if systemctl is-active --quiet docker; then
|
|
log_success "Docker 服务重启成功"
|
|
else
|
|
log_error "Docker 服务重启失败"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 显示可用镜像源
|
|
show_available_mirrors() {
|
|
log_title "可用 Docker 镜像源"
|
|
echo
|
|
printf "%-15s %-50s\n" "名称" "地址"
|
|
printf "%-15s %-50s\n" "----" "----------------------------------------"
|
|
for mirror_name in "${MIRROR_NAMES[@]}"; do
|
|
local mirror_var="MIRRORS_${mirror_name}"
|
|
local mirror_url="${!mirror_var}"
|
|
printf "%-15s %-50s\n" "$mirror_name" "$mirror_url"
|
|
done
|
|
echo
|
|
}
|
|
|
|
# 显示当前配置
|
|
show_current_config() {
|
|
log_title "当前 Docker 配置"
|
|
echo
|
|
|
|
if [[ ! -f "$DOCKER_CONFIG" ]]; then
|
|
echo "暂无配置文件"
|
|
return
|
|
fi
|
|
|
|
local config=$(get_current_config)
|
|
|
|
# 检查是否有 registry-mirrors
|
|
if echo "$config" | jq -e '.["registry-mirrors"]' >/dev/null 2>&1; then
|
|
local mirrors=$(echo "$config" | jq -r '.["registry-mirrors"][]')
|
|
if [[ -n "$mirrors" ]]; then
|
|
echo "镜像加速器:"
|
|
echo "$mirrors" | while read -r mirror; do
|
|
# 反向查找镜像源名称
|
|
local name="未知"
|
|
for key in "${!MIRRORS[@]}"; do
|
|
if [[ "${MIRRORS[$key]}" == "$mirror" ]]; then
|
|
name="$key"
|
|
break
|
|
fi
|
|
done
|
|
echo " - $name ($mirror)"
|
|
done
|
|
else
|
|
echo "镜像加速器: 未配置"
|
|
fi
|
|
else
|
|
echo "镜像加速器: 未配置"
|
|
fi
|
|
|
|
# 显示其他配置
|
|
if echo "$config" | jq -e '.log-driver' >/dev/null 2>&1; then
|
|
local log_driver=$(echo "$config" | jq -r '.["log-driver"]')
|
|
echo "日志驱动: $log_driver"
|
|
fi
|
|
|
|
if echo "$config" | jq -e '.log-opts' >/dev/null 2>&1; then
|
|
local max_size=$(echo "$config" | jq -r '.["log-opts"]["max-size"] // empty')
|
|
local max_file=$(echo "$config" | jq -r '.["log-opts"]["max-file"] // empty')
|
|
if [[ -n "$max_size" && -n "$max_file" ]]; then
|
|
echo "日志配置: 最大文件大小 $max_size, 保留 $max_file 个文件"
|
|
fi
|
|
fi
|
|
echo
|
|
}
|
|
|
|
# 添加镜像源
|
|
add_mirror() {
|
|
local mirror_name="$1"
|
|
|
|
local mirror_var="MIRRORS_${mirror_name}"
|
|
if [[ -z "${!mirror_var}" ]]; then
|
|
log_error "未知的镜像源: $mirror_name"
|
|
show_available_mirrors
|
|
exit 1
|
|
fi
|
|
|
|
local mirror_url="${!mirror_var}"
|
|
|
|
check_config
|
|
backup_config
|
|
|
|
local config=$(get_current_config)
|
|
|
|
# 检查是否已存在
|
|
if echo "$config" | jq -e ".\"registry-mirrors\"[]? | select(. == \"$mirror_url\")" >/dev/null 2>&1; then
|
|
log_warning "镜像源 $mirror_name 已经配置"
|
|
return
|
|
fi
|
|
|
|
# 添加到配置中
|
|
if echo "$config" | jq -e '.["registry-mirrors"]' >/dev/null 2>&1; then
|
|
# 如果已存在 registry-mirrors 数组,添加到数组中
|
|
config=$(echo "$config" | jq --arg url "$mirror_url" '.["registry-mirrors"] += [$url]')
|
|
else
|
|
# 如果不存在,创建新的数组
|
|
config=$(echo "$config" | jq --arg url "$mirror_url" '. + {"registry-mirrors": [$url]}')
|
|
fi
|
|
|
|
update_config "$config"
|
|
log_success "已添加镜像源: $mirror_name ($mirror_url)"
|
|
}
|
|
|
|
# 删除镜像源
|
|
remove_mirror() {
|
|
local mirror_name="$1"
|
|
|
|
if [[ "$mirror_name" == "all" ]]; then
|
|
# 删除所有镜像源
|
|
check_config
|
|
backup_config
|
|
|
|
local config=$(get_current_config)
|
|
config=$(echo "$config" | jq 'del(.["registry-mirrors"])')
|
|
update_config "$config"
|
|
log_success "已删除所有镜像源"
|
|
return
|
|
fi
|
|
|
|
local mirror_var="MIRRORS_${mirror_name}"
|
|
if [[ -z "${!mirror_var}" ]]; then
|
|
log_error "未知的镜像源: $mirror_name"
|
|
show_available_mirrors
|
|
exit 1
|
|
fi
|
|
|
|
local mirror_url="${!mirror_var}"
|
|
|
|
check_config
|
|
backup_config
|
|
|
|
local config=$(get_current_config)
|
|
|
|
# 检查是否存在
|
|
if ! echo "$config" | jq -e ".\"registry-mirrors\"[]? | select(. == \"$mirror_url\")" >/dev/null 2>&1; then
|
|
log_warning "镜像源 $mirror_name 未配置"
|
|
return
|
|
fi
|
|
|
|
# 从配置中删除
|
|
config=$(echo "$config" | jq --arg url "$mirror_url" '.["registry-mirrors"] = (.["registry-mirrors"] | map(select(. != $url)))')
|
|
|
|
# 如果数组为空,删除整个键
|
|
if echo "$config" | jq -e '.["registry-mirrors"] | length == 0' >/dev/null 2>&1; then
|
|
config=$(echo "$config" | jq 'del(.["registry-mirrors"])')
|
|
fi
|
|
|
|
update_config "$config"
|
|
log_success "已删除镜像源: $mirror_name ($mirror_url)"
|
|
}
|
|
|
|
# 设置推荐镜像源组合
|
|
set_recommended() {
|
|
log_info "设置推荐的镜像源组合 (阿里云 + 网易 + 华为云)..."
|
|
|
|
check_config
|
|
backup_config
|
|
|
|
local config=$(get_current_config)
|
|
|
|
# 推荐的镜像源组合
|
|
local recommended_mirrors=(
|
|
"https://registry.cn-hangzhou.aliyuncs.com"
|
|
"https://hub-mirror.c.163.com"
|
|
"https://mirror-1.trustie.net"
|
|
)
|
|
|
|
# 创建新的配置
|
|
config=$(echo "$config" | jq --argjson mirrors "$(printf '%s\n' "${recommended_mirrors[@]}" | jq -R . | jq -s .)" '. + {"registry-mirrors": $mirrors}')
|
|
|
|
update_config "$config"
|
|
log_success "已设置推荐镜像源组合"
|
|
}
|
|
|
|
# 测试镜像源速度
|
|
test_mirrors() {
|
|
log_title "测试镜像源速度"
|
|
echo
|
|
|
|
local test_image="hello-world:latest"
|
|
|
|
# 清理可能存在的测试镜像
|
|
docker rmi "$test_image" >/dev/null 2>&1 || true
|
|
|
|
echo "测试镜像: $test_image"
|
|
echo "测试结果:"
|
|
printf "%-15s %-15s %-20s\n" "镜像源" "状态" "耗时"
|
|
printf "%-15s %-15s %-20s\n" "-------" "-----" "----"
|
|
|
|
for mirror_name in "${MIRROR_NAMES[@]}"; do
|
|
local mirror_var="MIRRORS_${mirror_name}"
|
|
local mirror_url="${!mirror_var}"
|
|
|
|
# 临时设置镜像源
|
|
check_config
|
|
local original_config=$(get_current_config)
|
|
local test_config=$(echo "$original_config" | jq --arg url "$mirror_url" '. + {"registry-mirrors": [$url]}')
|
|
echo "$test_config" > "$DOCKER_CONFIG"
|
|
|
|
restart_docker >/dev/null 2>&1
|
|
|
|
# 测试拉取镜像
|
|
local start_time=$(date +%s.%3N)
|
|
if timeout 30 docker pull "$test_image" >/dev/null 2>&1; then
|
|
local end_time=$(date +%s.%3N)
|
|
local duration=$(echo "$end_time - $start_time" | bc 2>/dev/null || echo "0")
|
|
printf "%-15s ${GREEN}%-15s${NC} %-20s\n" "$mirror_name" "成功" "${duration}s"
|
|
else
|
|
printf "%-15s ${RED}%-15s${NC} %-20s\n" "$mirror_name" "失败" "超时"
|
|
fi
|
|
|
|
# 清理测试镜像
|
|
docker rmi "$test_image" >/dev/null 2>&1 || true
|
|
done
|
|
|
|
# 恢复原始配置
|
|
echo "$original_config" > "$DOCKER_CONFIG"
|
|
restart_docker >/dev/null 2>&1
|
|
|
|
echo
|
|
log_info "速度测试完成"
|
|
}
|
|
|
|
# 恢复备份配置
|
|
restore_config() {
|
|
local backup_file="$1"
|
|
|
|
if [[ -z "$backup_file" ]]; then
|
|
# 查找最新的备份文件
|
|
backup_file=$(ls -t /etc/docker/daemon.json.backup.* 2>/dev/null | head -1)
|
|
if [[ -z "$backup_file" ]]; then
|
|
log_error "未找到备份文件"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [[ ! -f "$backup_file" ]]; then
|
|
log_error "备份文件不存在: $backup_file"
|
|
exit 1
|
|
fi
|
|
|
|
cp "$backup_file" "$DOCKER_CONFIG"
|
|
log_success "已恢复配置: $backup_file"
|
|
}
|
|
|
|
# 显示帮助信息
|
|
show_help() {
|
|
cat << EOF
|
|
Docker 镜像加速器快速设置脚本
|
|
|
|
此脚本帮助您快速配置 Docker 镜像加速器,提升镜像拉取速度。
|
|
|
|
用法: $0 [选项] [操作] [参数]
|
|
|
|
操作:
|
|
list 显示可用镜像源
|
|
show 显示当前配置
|
|
add <镜像源> 添加镜像源 (例: add aliyun)
|
|
remove <镜像源> 删除镜像源 (例: remove aliyun)
|
|
remove all 删除所有镜像源
|
|
recommend 设置推荐镜像源组合
|
|
test 测试各镜像源速度
|
|
restore [文件] 恢复备份配置
|
|
restart 重启 Docker 服务
|
|
demo 演示模式 (无需 root 权限)
|
|
|
|
选项:
|
|
-h, --help 显示此帮助信息
|
|
|
|
可用镜像源:
|
|
aliyun - 阿里云镜像加速器
|
|
tencent - 腾讯云镜像加速器
|
|
huawei - 华为云镜像加速器
|
|
netease - 网易镜像加速器 (推荐)
|
|
ustc - 中科大镜像加速器
|
|
docker_cn - Docker 中国官方镜像
|
|
baidu - 百度云镜像加速器
|
|
tsinghua - 清华大学镜像加速器 (推荐)
|
|
|
|
示例:
|
|
$0 demo # 演示模式
|
|
sudo $0 list # 显示可用镜像源
|
|
sudo $0 show # 显示当前配置
|
|
sudo $0 add aliyun # 添加阿里云镜像源
|
|
sudo $0 add netease # 添加网易镜像源
|
|
sudo $0 recommend # 设置推荐组合 (阿里云+网易+华为云)
|
|
sudo $0 test # 测试镜像源速度
|
|
sudo $0 remove aliyun # 删除阿里云镜像源
|
|
sudo $0 remove all # 删除所有镜像源
|
|
sudo $0 restart # 重启 Docker 服务
|
|
|
|
EOF
|
|
}
|
|
|
|
# 主函数
|
|
main() {
|
|
# 检查演示模式
|
|
if [[ "$1" == "demo" ]]; then
|
|
log_title "Docker 镜像加速器设置脚本 - 演示模式"
|
|
echo
|
|
show_available_mirrors
|
|
echo "注意: 实际配置需要 root 权限"
|
|
echo "运行: sudo $0 [操作]"
|
|
echo
|
|
exit 0
|
|
fi
|
|
|
|
# 检查是否为 root 用户
|
|
if [[ $EUID -ne 0 ]]; then
|
|
log_error "请使用 root 用户或 sudo 运行此脚本"
|
|
echo "提示: 使用 '$0 demo' 查看演示"
|
|
exit 1
|
|
fi
|
|
|
|
# 检查 jq 是否安装
|
|
if ! command -v jq &> /dev/null; then
|
|
log_info "安装 jq 工具..."
|
|
apt update && apt install -y jq
|
|
fi
|
|
|
|
# 检查 bc 是否安装(用于速度测试)
|
|
if ! command -v bc &> /dev/null; then
|
|
apt install -y bc
|
|
fi
|
|
|
|
local action="$1"
|
|
shift
|
|
|
|
case $action in
|
|
list)
|
|
show_available_mirrors
|
|
;;
|
|
show)
|
|
check_docker
|
|
show_current_config
|
|
;;
|
|
add)
|
|
check_docker
|
|
if [[ $# -eq 0 ]]; then
|
|
log_error "请指定要添加的镜像源"
|
|
show_available_mirrors
|
|
exit 1
|
|
fi
|
|
add_mirror "$1"
|
|
restart_docker
|
|
;;
|
|
remove)
|
|
check_docker
|
|
if [[ $# -eq 0 ]]; then
|
|
log_error "请指定要删除的镜像源"
|
|
exit 1
|
|
fi
|
|
remove_mirror "$1"
|
|
restart_docker
|
|
;;
|
|
recommend)
|
|
check_docker
|
|
set_recommended
|
|
restart_docker
|
|
;;
|
|
test)
|
|
check_docker
|
|
test_mirrors
|
|
;;
|
|
restore)
|
|
restore_config "$1"
|
|
restart_docker
|
|
;;
|
|
restart)
|
|
check_docker
|
|
restart_docker
|
|
;;
|
|
""|-h|--help)
|
|
show_help
|
|
;;
|
|
*)
|
|
log_error "未知操作: $action"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
log_success "操作完成"
|
|
}
|
|
|
|
# 执行主函数
|
|
main "$@"
|