184 lines
6.0 KiB
Bash
Executable File
184 lines
6.0 KiB
Bash
Executable File
#!/bin/bash
|
||
# Docker 镜像源配置脚本
|
||
# 用于配置国内 Docker 镜像加速器,解决无法访问 Docker Hub 的问题
|
||
|
||
# 注意: 在关键步骤使用 set -e,但在用户交互和测试部分不使用
|
||
set -e
|
||
|
||
echo "=== Docker 镜像源配置脚本 ==="
|
||
echo ""
|
||
|
||
# 检查是否以 root 权限运行
|
||
if [ "$EUID" -ne 0 ]; then
|
||
echo "错误: 请使用 sudo 运行此脚本"
|
||
exit 1
|
||
fi
|
||
|
||
# 创建 Docker 配置目录
|
||
mkdir -p /etc/docker
|
||
|
||
# 检查是否已存在 daemon.json
|
||
BACKUP_CREATED=false
|
||
if [ -f /etc/docker/daemon.json ]; then
|
||
echo "检测到已存在的 /etc/docker/daemon.json 文件"
|
||
echo "将保留现有配置(如存储路径等),只更新镜像源配置"
|
||
read -p "是否备份现有配置?(y/n) " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
cp /etc/docker/daemon.json /etc/docker/daemon.json.backup.$(date +%Y%m%d_%H%M%S)
|
||
BACKUP_CREATED=true
|
||
echo "已备份到 /etc/docker/daemon.json.backup.*"
|
||
fi
|
||
|
||
# 读取现有配置并合并镜像源
|
||
echo "合并现有配置和镜像源配置..."
|
||
|
||
# 使用 Python 来安全地合并 JSON 配置(保留所有现有配置)
|
||
python3 << 'PYTHON_SCRIPT'
|
||
import json
|
||
import sys
|
||
|
||
# 镜像源列表
|
||
mirrors = [
|
||
"https://docker.m.daocloud.io",
|
||
"https://hub-mirror.c.163.com",
|
||
"https://docker.mirrors.ustc.edu.cn",
|
||
"https://docker.nju.edu.cn",
|
||
"https://docker.1panel.live"
|
||
]
|
||
|
||
try:
|
||
# 读取现有配置
|
||
with open('/etc/docker/daemon.json', 'r', encoding='utf-8') as f:
|
||
config = json.load(f)
|
||
except (FileNotFoundError, json.JSONDecodeError) as e:
|
||
print(f"Error reading existing config: {e}", file=sys.stderr)
|
||
sys.exit(1)
|
||
|
||
# 更新或添加 registry-mirrors
|
||
if 'registry-mirrors' in config:
|
||
# 合并现有镜像源和新镜像源(去重)
|
||
existing_mirrors = config.get('registry-mirrors', [])
|
||
combined_mirrors = list(dict.fromkeys(existing_mirrors + mirrors)) # 保持顺序并去重
|
||
config['registry-mirrors'] = combined_mirrors
|
||
print(f"已合并镜像源配置(保留 {len(existing_mirrors)} 个现有镜像源,添加 {len(mirrors)} 个新镜像源)")
|
||
else:
|
||
# 添加新的镜像源配置
|
||
config['registry-mirrors'] = mirrors
|
||
print("已添加镜像源配置")
|
||
|
||
# 写入合并后的配置
|
||
try:
|
||
with open('/etc/docker/daemon.json', 'w', encoding='utf-8') as f:
|
||
json.dump(config, f, indent=2, ensure_ascii=False)
|
||
print("✓ 配置已更新,所有现有配置(如存储路径等)已保留")
|
||
except Exception as e:
|
||
print(f"Error writing config: {e}", file=sys.stderr)
|
||
sys.exit(1)
|
||
PYTHON_SCRIPT
|
||
|
||
if [ $? -ne 0 ]; then
|
||
echo "错误: 合并配置失败"
|
||
if [ "$BACKUP_CREATED" = true ]; then
|
||
echo "可以从备份文件恢复: /etc/docker/daemon.json.backup.*"
|
||
fi
|
||
exit 1
|
||
fi
|
||
else
|
||
# 如果文件不存在,创建新配置
|
||
echo "配置 Docker 镜像源(创建新配置文件)..."
|
||
cat > /etc/docker/daemon.json <<EOF
|
||
{
|
||
"registry-mirrors": [
|
||
"https://docker.m.daocloud.io",
|
||
"https://hub-mirror.c.163.com",
|
||
"https://docker.mirrors.ustc.edu.cn",
|
||
"https://docker.nju.edu.cn",
|
||
"https://docker.1panel.live"
|
||
]
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
echo "✓ 已配置镜像源到 /etc/docker/daemon.json"
|
||
|
||
# 重新加载 Docker 配置
|
||
echo "重新加载 Docker 配置..."
|
||
systemctl daemon-reload
|
||
|
||
# 重启 Docker 服务
|
||
echo "重启 Docker 服务..."
|
||
systemctl restart docker
|
||
|
||
echo ""
|
||
echo "=== 配置完成 ==="
|
||
echo ""
|
||
|
||
# 验证配置是否生效
|
||
echo "验证配置是否生效..."
|
||
if docker info | grep -A 10 "Registry Mirrors" > /dev/null 2>&1; then
|
||
echo "✓ 镜像源配置已生效:"
|
||
docker info | grep -A 10 "Registry Mirrors"
|
||
else
|
||
echo "✗ 无法验证镜像源配置,请手动检查: docker info | grep -A 10 'Registry Mirrors'"
|
||
fi
|
||
|
||
echo ""
|
||
echo "测试拉取镜像(仅测试,不完整下载)..."
|
||
echo "提示: 这将尝试从镜像源拉取 ChromaDB 镜像,按 Ctrl+C 可以中断"
|
||
echo -n "是否继续测试?(y/n,默认n): "
|
||
# 确保在交互式环境中正确读取输入
|
||
if [ -t 0 ]; then
|
||
# 交互式终端
|
||
read -t 30 -n 1 -r REPLY
|
||
READ_STATUS=$?
|
||
echo "" # 换行
|
||
if [ $READ_STATUS -ne 0 ]; then
|
||
REPLY="n"
|
||
echo "(未收到输入,默认跳过测试)"
|
||
fi
|
||
else
|
||
# 非交互式终端,默认跳过
|
||
REPLY="n"
|
||
echo "n(非交互式终端,默认跳过测试)"
|
||
fi
|
||
|
||
if [[ "$REPLY" =~ ^[Yy]$ ]]; then
|
||
echo "开始测试拉取镜像 chromadb/chroma:1.3.5..."
|
||
echo "(测试将在30秒后自动停止,或按 Ctrl+C 中断)"
|
||
echo ""
|
||
# 使用 timeout 限制测试时间,并捕获输出
|
||
if timeout 30 docker pull chromadb/chroma:1.3.5 2>&1 | tee /tmp/docker_pull_test.log | head -30; then
|
||
echo ""
|
||
if grep -q "Pulling\|Downloading\|Pull complete" /tmp/docker_pull_test.log 2>/dev/null; then
|
||
echo "✓ 镜像拉取测试成功!镜像源配置正常工作。"
|
||
echo "提示: 看到下载进度说明镜像源配置成功。"
|
||
else
|
||
echo "⚠ 镜像拉取测试未显示下载进度"
|
||
echo "提示: 请检查网络连接或镜像源配置"
|
||
fi
|
||
rm -f /tmp/docker_pull_test.log 2>/dev/null
|
||
else
|
||
EXIT_CODE=${PIPESTATUS[0]}
|
||
if [ $EXIT_CODE -eq 124 ]; then
|
||
echo ""
|
||
echo "⏱ 测试超时(30秒),但这是正常的"
|
||
if grep -q "Pulling\|Downloading\|Pull complete" /tmp/docker_pull_test.log 2>/dev/null; then
|
||
echo "✓ 镜像源配置正常工作(已看到下载进度)"
|
||
else
|
||
echo "⚠ 未看到下载进度,请检查网络或手动测试"
|
||
fi
|
||
else
|
||
echo ""
|
||
echo "⚠ 镜像拉取测试失败(退出码: $EXIT_CODE)"
|
||
echo "提示: 请检查 Docker 服务状态和网络连接"
|
||
fi
|
||
rm -f /tmp/docker_pull_test.log 2>/dev/null
|
||
fi
|
||
else
|
||
echo "跳过测试。您可以稍后手动测试:"
|
||
echo " docker pull chromadb/chroma:1.3.5"
|
||
fi
|
||
echo ""
|
||
|