274 lines
6.8 KiB
Bash
274 lines
6.8 KiB
Bash
#!/bin/env bash
|
||
|
||
# Docker 安装脚本
|
||
# 支持中国大陆和海外环境
|
||
|
||
set -euo pipefail
|
||
|
||
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
readonly LOG_FILE="${SCRIPT_DIR}/docker_install.log"
|
||
readonly DAEMON_JSON="/etc/docker/daemon.json"
|
||
readonly BACKUP_FILE="${DAEMON_JSON}.backup"
|
||
|
||
# 颜色定义
|
||
readonly RED='\033[0;31m'
|
||
readonly GREEN='\033[0;32m'
|
||
readonly YELLOW='\033[1;33m'
|
||
readonly BLUE='\033[0;34m'
|
||
readonly NC='\033[0m' # No Color
|
||
|
||
# 日志函数
|
||
log() {
|
||
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_info() {
|
||
echo -e "${BLUE}[INFO]${NC} $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_warn() {
|
||
echo -e "${YELLOW}[WARN]${NC} $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
# 检测地区
|
||
detect_region() {
|
||
local country
|
||
country=$(curl -s --connect-timeout 5 --max-time 10 ipinfo.io/country 2>/dev/null || echo "")
|
||
[[ "$country" == "CN" ]]
|
||
}
|
||
|
||
# 检查Docker版本
|
||
check_docker_version() {
|
||
if ! command -v docker &>/dev/null; then
|
||
return 1
|
||
fi
|
||
|
||
local version
|
||
version=$(docker --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+' | head -n1)
|
||
local major="${version%%.*}"
|
||
|
||
if [[ ${major:-0} -lt 20 ]]; then
|
||
log_warn "Docker版本过低 (${version}),建议升级到20.x或更高版本"
|
||
else
|
||
log_info "检测到Docker版本: ${version}"
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# 创建daemon.json配置
|
||
create_daemon_json() {
|
||
local accelerator_url="${1:-}"
|
||
|
||
if [[ -n "$accelerator_url" ]]; then
|
||
log_info "配置Docker镜像加速器: $accelerator_url"
|
||
cat > "$DAEMON_JSON" << EOF
|
||
{
|
||
"registry-mirrors": ["$accelerator_url"],
|
||
"log-driver": "json-file",
|
||
"log-opts": {
|
||
"max-size": "100m",
|
||
"max-file": "3"
|
||
},
|
||
"storage-driver": "overlay2"
|
||
}
|
||
EOF
|
||
else
|
||
cat > "$DAEMON_JSON" << EOF
|
||
{
|
||
"log-driver": "json-file",
|
||
"log-opts": {
|
||
"max-size": "100m",
|
||
"max-file": "3"
|
||
},
|
||
"storage-driver": "overlay2"
|
||
}
|
||
EOF
|
||
fi
|
||
}
|
||
|
||
# 配置加速器
|
||
configure_accelerator() {
|
||
if ! detect_region; then
|
||
log_info "非中国大陆地区,跳过镜像加速器配置"
|
||
return 0
|
||
fi
|
||
|
||
echo -n "是否配置Docker镜像加速器?(y/N): "
|
||
read -r choice
|
||
|
||
case "$choice" in
|
||
[yY]|[yY][eE][sS])
|
||
local accelerator_url=""
|
||
|
||
# 测试腾讯云镜像可用性
|
||
if ping -c 1 -W 3 mirror.ccs.tencentyun.com &>/dev/null; then
|
||
accelerator_url="https://mirror.ccs.tencentyun.com"
|
||
else
|
||
# 备选阿里云镜像
|
||
accelerator_url="https://registry.cn-hangzhou.aliyuncs.com"
|
||
fi
|
||
|
||
# 备份现有配置
|
||
[[ -f "$DAEMON_JSON" ]] && cp "$DAEMON_JSON" "$BACKUP_FILE"
|
||
|
||
# 创建配置目录
|
||
mkdir -p "$(dirname "$DAEMON_JSON")"
|
||
|
||
# 创建新配置
|
||
create_daemon_json "$accelerator_url"
|
||
|
||
# 重启Docker服务
|
||
log_info "重启Docker服务..."
|
||
systemctl daemon-reload
|
||
systemctl restart docker
|
||
|
||
log "Docker镜像加速器配置完成"
|
||
;;
|
||
*)
|
||
log_info "跳过镜像加速器配置"
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# 获取最快的Docker安装源
|
||
get_fastest_source() {
|
||
local sources=(
|
||
"https://mirrors.aliyun.com/docker-ce"
|
||
"https://mirrors.tencent.com/docker-ce"
|
||
"https://mirrors.163.com/docker-ce"
|
||
)
|
||
|
||
local fastest_source="${sources[0]}"
|
||
local min_time=99999
|
||
|
||
for source in "${sources[@]}"; do
|
||
local response_time
|
||
response_time=$(curl -o /dev/null -s -w '%{time_total}\n' -m 3 "$source" 2>/dev/null || echo "99999")
|
||
|
||
if (( $(echo "$response_time < $min_time" | bc -l 2>/dev/null || echo 0) )); then
|
||
min_time=$response_time
|
||
fastest_source=$source
|
||
fi
|
||
done
|
||
|
||
echo "$fastest_source"
|
||
}
|
||
|
||
# 下载Docker安装脚本
|
||
download_docker_script() {
|
||
local scripts=(
|
||
"https://get.docker.com"
|
||
"https://cdn.jsdelivr.net/gh/docker/docker-install@master/install.sh"
|
||
"https://fastly.jsdelivr.net/gh/docker/docker-install@master/install.sh"
|
||
)
|
||
|
||
for script_url in "${scripts[@]}"; do
|
||
log_info "尝试从 $script_url 下载安装脚本..."
|
||
|
||
if curl -fsSL --connect-timeout 10 --max-time 30 "$script_url" -o get-docker.sh; then
|
||
log "下载成功: $script_url"
|
||
return 0
|
||
else
|
||
log_warn "下载失败: $script_url"
|
||
fi
|
||
done
|
||
|
||
log_error "所有下载尝试均失败"
|
||
return 1
|
||
}
|
||
|
||
# 安装Docker
|
||
install_docker() {
|
||
log_info "开始安装Docker..."
|
||
|
||
if detect_region; then
|
||
log_info "检测到中国大陆地区,使用国内镜像源"
|
||
local fastest_source
|
||
fastest_source=$(get_fastest_source)
|
||
export DOWNLOAD_URL="$fastest_source"
|
||
log_info "选择最快源: $fastest_source"
|
||
else
|
||
log_info "使用官方源"
|
||
export DOWNLOAD_URL="https://download.docker.com"
|
||
fi
|
||
|
||
# 下载安装脚本
|
||
if ! download_docker_script; then
|
||
log_error "无法下载Docker安装脚本"
|
||
return 1
|
||
fi
|
||
|
||
# 执行安装
|
||
log_info "执行Docker安装..."
|
||
if sh get-docker.sh 2>&1 | tee -a "$LOG_FILE"; then
|
||
log "Docker安装成功"
|
||
else
|
||
log_error "Docker安装失败"
|
||
return 1
|
||
fi
|
||
|
||
# 清理安装脚本
|
||
rm -f get-docker.sh
|
||
|
||
# 启动并启用Docker服务
|
||
log_info "启动Docker服务..."
|
||
systemctl enable docker
|
||
systemctl start docker
|
||
|
||
# 验证安装
|
||
if docker --version &>/dev/null; then
|
||
log "Docker安装验证成功"
|
||
docker --version | tee -a "$LOG_FILE"
|
||
return 0
|
||
else
|
||
log_error "Docker安装验证失败"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 主函数
|
||
main() {
|
||
log "开始Docker安装检查..."
|
||
|
||
# 检查是否已安装Docker
|
||
if check_docker_version; then
|
||
log_info "Docker已安装"
|
||
configure_accelerator
|
||
return 0
|
||
fi
|
||
|
||
# 确认安装
|
||
echo -n "Docker未安装,是否现在安装?(y/N): "
|
||
read -r install_choice
|
||
|
||
case "$install_choice" in
|
||
[yY]|[yY][eE][sS])
|
||
if install_docker; then
|
||
configure_accelerator
|
||
log "Docker安装和配置完成!"
|
||
else
|
||
log_error "Docker安装失败,请检查日志: $LOG_FILE"
|
||
exit 1
|
||
fi
|
||
;;
|
||
*)
|
||
log_info "取消安装"
|
||
exit 0
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# 检查root权限
|
||
if [[ $EUID -ne 0 ]]; then
|
||
log_error "此脚本需要root权限运行"
|
||
exit 1
|
||
fi
|
||
|
||
# 执行主函数
|
||
main "$@"
|