docs: add docker compose and buildx upgrade guide
- add a standalone docs guide for reinstalling Docker, Compose, and Buildx from the official Ubuntu repository - refine planet.sh compose/build diagnostics so docker compose is the primary wording and missing buildx / fallback cases report more accurately - keep the startup failure output aligned with the existing terminal tone while reducing misleading compose-version messaging
This commit is contained in:
105
docs/docker-compose-buildx-upgrade.md
Normal file
105
docs/docker-compose-buildx-upgrade.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# Docker + Compose + Buildx 升级教程
|
||||
|
||||
流程:删除旧版 -> 安装新版 -> 验证
|
||||
|
||||
---
|
||||
|
||||
# 1. 删除旧版本
|
||||
|
||||
## 删除 apt 安装的旧包
|
||||
|
||||
```bash
|
||||
sudo apt remove -y docker.io docker-compose docker-compose-v2 docker-doc podman-docker containerd runc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 删除系统中的 `docker-compose`(V1)
|
||||
|
||||
```bash
|
||||
sudo rm -f "$(which docker-compose 2>/dev/null)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 查找并删除手动安装的 Buildx 插件
|
||||
|
||||
```bash
|
||||
docker info | sed -n '/Plugins:/,/^ Server:/p' | grep -A2 buildx
|
||||
```
|
||||
|
||||
从输出中获取 `Path`,然后执行:
|
||||
|
||||
```bash
|
||||
rm -f <Path中对应的docker-buildx文件>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 清理无用依赖
|
||||
|
||||
```bash
|
||||
sudo apt autoremove -y
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 2. 安装 Docker 官方版本
|
||||
|
||||
包含 Docker Engine、Docker Compose 插件、Docker Buildx 插件。
|
||||
|
||||
## 安装依赖
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install -y ca-certificates curl gnupg
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 添加 Docker GPG key
|
||||
|
||||
```bash
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
|
||||
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 添加官方仓库
|
||||
|
||||
```bash
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
||||
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 安装 Docker + Compose + Buildx
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 3. 验证安装
|
||||
|
||||
```bash
|
||||
docker --version
|
||||
docker compose version
|
||||
docker buildx version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 4. 常用命令
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
docker compose down
|
||||
docker buildx build .
|
||||
```
|
||||
130
planet.sh
130
planet.sh
@@ -84,7 +84,7 @@ ensure_local_runtime_bins_on_path() {
|
||||
ensure_local_runtime_bins_on_path
|
||||
|
||||
# Shell / Docker helpers
|
||||
compose_v2_available() {
|
||||
compose_available() {
|
||||
docker compose version >/dev/null 2>&1
|
||||
}
|
||||
|
||||
@@ -95,9 +95,9 @@ compose_v1_available() {
|
||||
report_missing_compose() {
|
||||
clear_wait_spinner
|
||||
log_error "未检测到可用的 Docker Compose"
|
||||
log_note "优先需要 Docker Compose v2 (`docker compose`)"
|
||||
log_note '优先使用 `docker compose`'
|
||||
log_note "如果当前机器仍只装有旧版 `docker-compose`,也请确认该命令可执行"
|
||||
log_note "推荐安装 Docker Compose v2 插件:"
|
||||
log_note "推荐安装 Docker Compose 插件:"
|
||||
log_note ' mkdir -p ~/.docker/cli-plugins'
|
||||
log_note ' curl -SL https://github.com/docker/compose/releases/download/v2.40.3/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose'
|
||||
log_note ' chmod +x ~/.docker/cli-plugins/docker-compose'
|
||||
@@ -105,16 +105,53 @@ report_missing_compose() {
|
||||
return 1
|
||||
}
|
||||
|
||||
buildx_version() {
|
||||
docker buildx version 2>/dev/null | awk '{print $2}' | sed 's/^v//'
|
||||
}
|
||||
|
||||
buildx_meets_minimum() {
|
||||
local current_version="$1"
|
||||
local required_version="$2"
|
||||
|
||||
[ -n "$current_version" ] || return 1
|
||||
[ -n "$required_version" ] || return 1
|
||||
|
||||
if [ "$(printf '%s\n%s\n' "$required_version" "$current_version" | sort -V | head -n 1)" = "$required_version" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
log_buildx_diagnostics_if_needed() {
|
||||
local current_buildx_version=""
|
||||
local required_buildx_version="0.17.0"
|
||||
|
||||
current_buildx_version="$(buildx_version)"
|
||||
|
||||
if [ -z "$current_buildx_version" ]; then
|
||||
log_note "未检测到 docker buildx,AI Provider 镜像构建依赖 buildx。"
|
||||
log_note "请先执行: docker buildx version"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! buildx_meets_minimum "$current_buildx_version" "$required_buildx_version"; then
|
||||
log_note "检测到 docker buildx 当前版本为 v${current_buildx_version},但 compose build 需要 v${required_buildx_version} 或更高。"
|
||||
log_note "可先升级 buildx 插件,再重新执行 ./planet.sh start"
|
||||
log_note "请先执行: docker buildx version"
|
||||
fi
|
||||
}
|
||||
|
||||
compose_up() {
|
||||
local args=("$@")
|
||||
local arg_text="$*"
|
||||
|
||||
if compose_v2_available; then
|
||||
set_wait_detail "正在用 docker compose v2 执行: ${arg_text}"
|
||||
if compose_available; then
|
||||
set_wait_detail "正在用 docker compose 执行: ${arg_text}"
|
||||
if docker compose "${args[@]}"; then
|
||||
return 0
|
||||
fi
|
||||
log_warn "docker compose v2 执行失败,回退到 docker-compose v1"
|
||||
log_warn "docker compose 执行失败,回退到 docker-compose v1"
|
||||
fi
|
||||
|
||||
if compose_v1_available; then
|
||||
@@ -123,7 +160,7 @@ compose_up() {
|
||||
return 0
|
||||
fi
|
||||
clear_wait_spinner
|
||||
log_error "docker compose v2 与 docker-compose v1 均执行失败"
|
||||
log_error "docker compose 与 docker-compose v1 均执行失败"
|
||||
log_note "最后尝试的命令: docker-compose ${arg_text}"
|
||||
return 1
|
||||
fi
|
||||
@@ -132,7 +169,7 @@ compose_up() {
|
||||
}
|
||||
|
||||
compose_supports_build() {
|
||||
if compose_v2_available; then
|
||||
if compose_available; then
|
||||
docker compose build --help >/dev/null 2>&1 && return 0
|
||||
fi
|
||||
if compose_v1_available; then
|
||||
@@ -392,6 +429,58 @@ run_with_retry() {
|
||||
return 1
|
||||
}
|
||||
|
||||
docker_daemon_available() {
|
||||
docker info >/dev/null 2>&1
|
||||
}
|
||||
|
||||
log_docker_daemon_diagnostics() {
|
||||
local docker_service_status=""
|
||||
local docker_socket_status=""
|
||||
local service_hint="sudo systemctl enable --now docker.socket && sudo systemctl restart docker"
|
||||
|
||||
docker_service_status="$(systemctl is-active docker 2>/dev/null || true)"
|
||||
docker_socket_status="$(systemctl is-active docker.socket 2>/dev/null || true)"
|
||||
|
||||
if [ -S /var/run/docker.sock ] && [ ! -r /var/run/docker.sock ]; then
|
||||
log_note "检测到 /var/run/docker.sock 存在,但当前用户无法访问。"
|
||||
log_note "请确认当前用户已加入 docker 组,并重新登录会话。"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$docker_service_status" = "active" ]; then
|
||||
log_note "Docker CLI 可执行,但当前会话仍无法连接 daemon。"
|
||||
log_note "请先执行: docker info"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$docker_service_status" = "failed" ] || [ "$docker_socket_status" = "failed" ]; then
|
||||
log_note "检测到 Docker daemon 当前未正常运行。"
|
||||
log_note "可先执行: ${service_hint}"
|
||||
log_note "如仍失败,继续查看: journalctl -u docker.service -n 50 --no-pager"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$docker_socket_status" != "active" ]; then
|
||||
log_note "检测到 Docker socket 未激活,daemon 可能无法通过 systemd socket activation 启动。"
|
||||
log_note "可先执行: ${service_hint}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_note "当前无法连接 Docker daemon,请先执行: docker info"
|
||||
log_note "若 daemon 未启动,可尝试: ${service_hint}"
|
||||
}
|
||||
|
||||
print_database_failure_diagnostics() {
|
||||
if ! docker_daemon_available; then
|
||||
log_note "数据库容器尚未真正开始启动,当前失败更像是 Docker 运行时不可用。"
|
||||
log_docker_daemon_diagnostics
|
||||
return 0
|
||||
fi
|
||||
|
||||
docker logs --tail 20 planet_postgres 2>/dev/null || true
|
||||
docker logs --tail 20 planet_redis 2>/dev/null || true
|
||||
}
|
||||
|
||||
compute_ai_provider_build_fingerprint() {
|
||||
(
|
||||
cd "$SCRIPT_DIR" || exit 1
|
||||
@@ -481,6 +570,7 @@ ensure_ai_provider_image_current() {
|
||||
clear_wait_spinner
|
||||
log_error "AI Provider 镜像构建失败"
|
||||
tail -20 "$AI_PROVIDER_BUILD_LOG_FILE" 2>/dev/null || true
|
||||
log_buildx_diagnostics_if_needed
|
||||
exit 1
|
||||
fi
|
||||
log_success "AI Provider 镜像已构建"
|
||||
@@ -490,12 +580,17 @@ ensure_ai_provider_image_current() {
|
||||
}
|
||||
|
||||
build_ai_provider_image_with_fallback() {
|
||||
if compose_v2_available; then
|
||||
set_wait_detail "使用 Docker Compose v2 构建 AI Provider 镜像"
|
||||
if compose_available; then
|
||||
set_wait_detail "使用 docker compose 构建 AI Provider 镜像"
|
||||
if run_command_with_spinner "构建 AI Provider 镜像" sh -c "docker compose build aiprovider > \"$AI_PROVIDER_BUILD_LOG_FILE\" 2>&1"; then
|
||||
return 0
|
||||
fi
|
||||
log_warn "Docker Compose v2 构建失败,回退到 docker-compose v1"
|
||||
if compose_v1_available; then
|
||||
log_warn "docker compose 构建失败,回退到 docker-compose v1"
|
||||
else
|
||||
log_warn "docker compose 构建失败,当前环境未安装 docker-compose v1,无法继续回退"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if compose_v1_available; then
|
||||
@@ -969,8 +1064,7 @@ ensure_database_services_healthy() {
|
||||
|
||||
if [ "$retry" -eq "$DATABASE_START_MAX_RETRIES" ]; then
|
||||
log_error "数据库启动失败,已重试 ${DATABASE_START_MAX_RETRIES} 次"
|
||||
docker logs --tail 20 planet_postgres 2>/dev/null || true
|
||||
docker logs --tail 20 planet_redis 2>/dev/null || true
|
||||
print_database_failure_diagnostics
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -990,7 +1084,12 @@ ensure_postgres_service_healthy() {
|
||||
|
||||
if [ "$retry" -eq "$DATABASE_START_MAX_RETRIES" ]; then
|
||||
log_error "PostgreSQL 启动失败,已重试 ${DATABASE_START_MAX_RETRIES} 次"
|
||||
docker logs --tail 20 planet_postgres 2>/dev/null || true
|
||||
if ! docker_daemon_available; then
|
||||
log_note "PostgreSQL 容器尚未真正开始启动,当前失败更像是 Docker 运行时不可用。"
|
||||
log_docker_daemon_diagnostics
|
||||
else
|
||||
docker logs --tail 20 planet_postgres 2>/dev/null || true
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -1012,8 +1111,7 @@ restart_database_service() {
|
||||
|
||||
if [ "$retry" -eq "$DATABASE_START_MAX_RETRIES" ]; then
|
||||
log_error "数据库重启失败,已重试 ${DATABASE_START_MAX_RETRIES} 次"
|
||||
docker logs --tail 20 planet_postgres 2>/dev/null || true
|
||||
docker logs --tail 20 planet_redis 2>/dev/null || true
|
||||
print_database_failure_diagnostics
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user