release: bump version to 0.74.3
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / delivery (push) Has been cancelled
release / images (push) Has been cancelled
ci / backend (pull_request) Has been cancelled
ci / frontend (pull_request) Has been cancelled
ci / delivery (pull_request) Has been cancelled
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / delivery (push) Has been cancelled
release / images (push) Has been cancelled
ci / backend (pull_request) Has been cancelled
ci / frontend (pull_request) Has been cancelled
ci / delivery (pull_request) Has been cancelled
This commit is contained in:
239
scripts/lib/docker-bootstrap.zsh
Normal file
239
scripts/lib/docker-bootstrap.zsh
Normal file
@@ -0,0 +1,239 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
# Docker prerequisites for planet.sh; lifecycle and logging remain in planet.sh.
|
||||
DOCKER_MIN_BUILDX_VERSION="0.17.0"
|
||||
|
||||
compose_available() {
|
||||
docker compose version >/dev/null 2>&1
|
||||
}
|
||||
|
||||
compose_v1_available() {
|
||||
command -v docker-compose >/dev/null 2>&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
|
||||
}
|
||||
|
||||
docker_daemon_available() {
|
||||
command -v docker >/dev/null 2>&1 && command docker info >/dev/null 2>&1
|
||||
}
|
||||
|
||||
docker_uses_local_engine() {
|
||||
local endpoint="${DOCKER_HOST:-}"
|
||||
if [ -n "${DOCKER_CONTEXT:-}" ] || [ -z "$endpoint" ]; then
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
endpoint="$(command docker context inspect --format '{{.Endpoints.docker.Host}}' 2>/dev/null)" || return 1
|
||||
elif [ -n "${DOCKER_CONTEXT:-}" ]; then
|
||||
return 1
|
||||
else
|
||||
endpoint="unix:///var/run/docker.sock"
|
||||
fi
|
||||
fi
|
||||
case "$endpoint" in
|
||||
unix:///var/run/docker.sock|unix:///run/docker.sock) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
docker_desktop_present() {
|
||||
local docker_path=""
|
||||
[ -d /mnt/wsl/docker-desktop ] && return 0
|
||||
docker_path="$(command -v docker 2>/dev/null || true)"
|
||||
[ -n "$docker_path" ] || return 1
|
||||
docker_path="$(readlink -f "$docker_path" 2>/dev/null || true)"
|
||||
[[ "$docker_path" == */docker-desktop/* ]]
|
||||
}
|
||||
|
||||
docker_systemd_unit_exists() {
|
||||
command -v systemctl >/dev/null 2>&1 || return 1
|
||||
[ "$(systemctl show --property=LoadState --value "$1" 2>/dev/null)" = "loaded" ]
|
||||
}
|
||||
|
||||
docker_socket_needs_group_access() {
|
||||
[ -S /var/run/docker.sock ] && { [ ! -r /var/run/docker.sock ] || [ ! -w /var/run/docker.sock ]; }
|
||||
}
|
||||
|
||||
docker_require_sudo() {
|
||||
[ "$(id -u)" -eq 0 ] && return 0
|
||||
if ! command -v sudo >/dev/null 2>&1; then
|
||||
log_error "缺少 sudo,无法安装或配置 Docker;请先由管理员安装 sudo 并授予当前用户权限。"
|
||||
return 1
|
||||
fi
|
||||
# Authenticate in the foreground, before command output is redirected to a log.
|
||||
sudo -v
|
||||
}
|
||||
|
||||
docker_as_root() {
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
"$@"
|
||||
else
|
||||
sudo -- "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
refresh_docker_group() {
|
||||
[ "$(id -u)" -ne 0 ] || return 0
|
||||
command -v docker >/dev/null 2>&1 || return 0
|
||||
docker_uses_local_engine || return 0
|
||||
docker_socket_needs_group_access || return 0
|
||||
|
||||
local username="$(id -un)"
|
||||
local groups="$(id -nG "$username")"
|
||||
[[ " $groups " == *" docker "* ]] || return 0
|
||||
if [ "${PLANET_DOCKER_GROUP_REEXEC:-0}" = "1" ]; then
|
||||
log_error "刷新组权限后仍无法访问 Docker socket,请检查 socket 的属组和权限。"
|
||||
return 1
|
||||
fi
|
||||
docker_require_sudo || return 1
|
||||
log_note "刷新 Docker 组权限,以当前用户继续执行。"
|
||||
# Preserve WSL interop/tool paths even when sudo applies secure_path.
|
||||
# argv stays an array: repository paths and arguments are never evaluated as shell text.
|
||||
exec sudo -E -u "$username" -g docker -- env PLANET_DOCKER_GROUP_REEXEC=1 "PATH=$PATH" \
|
||||
"$(command -v zsh)" "$SCRIPT_DIR/planet.sh" "$@"
|
||||
}
|
||||
|
||||
docker_bootstrap_os_id() {
|
||||
[ -r /etc/os-release ] || return 1
|
||||
(. /etc/os-release; printf '%s\n' "$ID")
|
||||
}
|
||||
|
||||
install_docker_prerequisites() {
|
||||
local log_file="$PLANET_STATE_DIR/docker_install.log"
|
||||
local engine_package="docker.io"
|
||||
local compose_package="docker-compose-v2"
|
||||
local buildx_package="docker-buildx"
|
||||
local -a packages=()
|
||||
|
||||
if [ "$(docker_bootstrap_os_id)" != "ubuntu" ] || ! command -v apt-get >/dev/null 2>&1; then
|
||||
log_error "Docker 自动安装目前支持 Ubuntu / Ubuntu WSL;请先安装本系统的 Docker Engine、Compose v2 和 Buildx。"
|
||||
return 1
|
||||
fi
|
||||
if command -v dpkg-query >/dev/null 2>&1 &&
|
||||
[ "$(dpkg-query -W -f='${Status}' docker-ce-cli 2>/dev/null)" = "install ok installed" ]; then
|
||||
engine_package="docker-ce"
|
||||
compose_package="docker-compose-plugin"
|
||||
buildx_package="docker-buildx-plugin"
|
||||
fi
|
||||
if ! command -v docker >/dev/null 2>&1 ||
|
||||
{ ! docker_daemon_available && ! command -v dockerd >/dev/null 2>&1; }; then
|
||||
packages+=("$engine_package")
|
||||
fi
|
||||
compose_available || packages+=("$compose_package")
|
||||
buildx_meets_minimum "$(buildx_version)" "$DOCKER_MIN_BUILDX_VERSION" || packages+=("$buildx_package")
|
||||
[ "${#packages[@]}" -gt 0 ] || return 0
|
||||
|
||||
docker_require_sudo || return 1
|
||||
log_step "安装 Docker 依赖: ${packages[*]}"
|
||||
if ! run_command_quiet_unless_verbose "$log_file" docker_as_root apt-get update --error-on=any ||
|
||||
! run_command_quiet_unless_verbose "$log_file" docker_as_root apt-get install -y "${packages[@]}"; then
|
||||
log_error "Docker 依赖安装失败,请检查软件源、网络和 apt 错误。"
|
||||
tail -20 "$log_file" 2>/dev/null || true
|
||||
return 1
|
||||
fi
|
||||
rehash
|
||||
}
|
||||
|
||||
start_local_docker_engine() {
|
||||
local log_file="$PLANET_STATE_DIR/docker_service.log"
|
||||
if ! docker_systemd_unit_exists docker.service; then
|
||||
log_error "没有可用的 docker.service;请确认 Docker Engine 已安装且 systemd 正常运行。"
|
||||
log_note "Ubuntu WSL 可在 /etc/wsl.conf 的 [boot] 下启用 systemd=true,再重启 WSL。"
|
||||
return 1
|
||||
fi
|
||||
docker_require_sudo || return 1
|
||||
if ! run_command_quiet_unless_verbose "$log_file" docker_as_root systemctl enable --now docker.service; then
|
||||
log_error "Docker Engine 启动失败。"
|
||||
tail -20 "$log_file" 2>/dev/null || true
|
||||
log_note "查看原因: journalctl -u docker.service -n 50 --no-pager"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_docker_user_access() {
|
||||
[ "$(id -u)" -ne 0 ] || return 0
|
||||
docker_socket_needs_group_access || return 0
|
||||
docker_require_sudo || return 1
|
||||
ensure_system_command usermod passwd "usermod" || return 1
|
||||
log_note "将当前用户加入 docker 组(该组可管理本机 Docker)。"
|
||||
docker_as_root usermod -aG docker "$(id -un)" || return 1
|
||||
refresh_docker_group "$@"
|
||||
}
|
||||
|
||||
ensure_docker_runtime() {
|
||||
if docker_daemon_available && compose_available &&
|
||||
buildx_meets_minimum "$(buildx_version)" "$DOCKER_MIN_BUILDX_VERSION"; then
|
||||
return 0
|
||||
fi
|
||||
if docker_desktop_present; then
|
||||
log_error "检测到 Docker Desktop,但当前 WSL 的 Docker / Compose / Buildx 尚不可用。"
|
||||
log_note "请启动 Docker Desktop,并为当前发行版启用 WSL Integration。"
|
||||
return 1
|
||||
fi
|
||||
if ! docker_uses_local_engine; then
|
||||
log_error "当前 Docker 使用其他 context 或远程/rootless endpoint,请先检查该环境的连接和插件。"
|
||||
return 1
|
||||
fi
|
||||
install_docker_prerequisites || return 1
|
||||
if ! command -v docker >/dev/null 2>&1 || ! compose_available ||
|
||||
! buildx_meets_minimum "$(buildx_version)" "$DOCKER_MIN_BUILDX_VERSION"; then
|
||||
log_error "安装后 Docker CLI、Compose v2 或 Buildx >= ${DOCKER_MIN_BUILDX_VERSION} 仍不可用。"
|
||||
return 1
|
||||
fi
|
||||
if ! docker_daemon_available; then
|
||||
start_local_docker_engine || return 1
|
||||
ensure_docker_user_access "$@" || return 1
|
||||
fi
|
||||
if ! docker_daemon_available; then
|
||||
log_error "Docker 已安装,但当前用户仍无法连接 daemon。"
|
||||
log_docker_daemon_diagnostics
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
log_docker_daemon_diagnostics() {
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
log_note "未找到 Docker CLI,尚未安装 Docker;Ubuntu / WSL 请先执行 ./planet.sh init。"
|
||||
return 0
|
||||
fi
|
||||
if docker_desktop_present; then
|
||||
log_note "请启动 Docker Desktop,并确认当前 WSL 已启用 WSL Integration。"
|
||||
return 0
|
||||
fi
|
||||
if ! docker_uses_local_engine; then
|
||||
log_note "当前使用其他 Docker endpoint;请检查 docker context ls 和 docker info。"
|
||||
return 0
|
||||
fi
|
||||
if docker_socket_needs_group_access; then
|
||||
log_note "Docker socket 存在,但当前用户没有读写权限;请执行 ./planet.sh init 配置 docker 组。"
|
||||
return 0
|
||||
fi
|
||||
if ! docker_systemd_unit_exists docker.service; then
|
||||
log_note "未检测到可用的 docker.service;Ubuntu / WSL 请执行 ./planet.sh init 检查安装。"
|
||||
return 0
|
||||
fi
|
||||
if [ "$(systemctl is-active docker.service 2>/dev/null)" = "active" ]; then
|
||||
log_note "Docker 服务已启动,但 CLI 无法连接;请检查 docker context ls 和 docker info。"
|
||||
return 0
|
||||
fi
|
||||
if docker_systemd_unit_exists docker.socket; then
|
||||
log_note "可先执行: sudo systemctl enable --now docker.socket && sudo systemctl restart docker.service"
|
||||
else
|
||||
log_note "可先执行: sudo systemctl enable --now docker.service"
|
||||
fi
|
||||
log_note "如仍失败,查看: journalctl -u docker.service -n 50 --no-pager"
|
||||
}
|
||||
Reference in New Issue
Block a user