优化数据库

This commit is contained in:
yml2213
2026-07-10 08:47:08 +08:00
parent 3318ed18ee
commit ce01c2aa34
9 changed files with 790 additions and 102 deletions
+141 -2
View File
@@ -2,7 +2,9 @@
set -Eeuo pipefail
# Ubuntu 服务器一键部署脚本。
# 用法:bash deploy/ubuntu-deploy.sh
# 用法:
# bash deploy/ubuntu-deploy.sh
# bash deploy/ubuntu-deploy.sh --reset-db
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ENV_FILE="${PROJECT_ROOT}/.env"
@@ -12,6 +14,8 @@ BACKEND_CONTAINER_UID=1001
BACKEND_CONTAINER_GID=1001
HEALTH_URL=""
READY_TIMEOUT="${READY_TIMEOUT:-120}"
RESET_DB=false
RESET_DB_CONFIRM="${RESET_DB_CONFIRM:-}"
log() {
printf '\033[1;34m[deploy]\033[0m %s\n' "$*"
@@ -26,6 +30,44 @@ fail() {
exit 1
}
print_usage() {
cat <<'EOF'
用法:
bash deploy/ubuntu-deploy.sh
bash deploy/ubuntu-deploy.sh --reset-db
参数:
--reset-db 删除 Compose PostgreSQL 数据卷 postgres_data,并用当前 001_init.sql 重建数据库。
--yes 跳过 --reset-db 的交互确认,也可使用环境变量 RESET_DB_CONFIRM=1。
-h, --help 显示帮助。
注意:
--reset-db 会删除所有 PostgreSQL 数据,包括订单、任务、后台用户、审计日志和迁移记录。
它不会删除 apps/backend/data 下的平台 JSON 配置,也不会删除 Caddy 证书卷。
EOF
}
parse_args() {
while (($# > 0)); do
case "$1" in
--reset-db)
RESET_DB=true
;;
--yes)
RESET_DB_CONFIRM=1
;;
-h|--help)
print_usage
exit 0
;;
*)
fail "未知参数:$1。执行 bash deploy/ubuntu-deploy.sh --help 查看用法。"
;;
esac
shift
done
}
read_env_value() {
local key="$1"
awk -F= -v key="${key}" '
@@ -86,6 +128,40 @@ validate_database_url_for_compose() {
fi
}
validate_reset_database_target() {
local database_url
database_url="$(read_env_value DATABASE_URL)"
if [[ -n "${database_url}" && "${database_url}" != *"@postgres:"* ]]; then
fail "--reset-db 只支持重置本脚本管理的 Compose PostgreSQL。当前 DATABASE_URL 未指向 postgres 服务,请手动确认外部数据库后再处理。"
fi
}
confirm_reset_database() {
if [[ "${RESET_DB}" != "true" ]]; then
return
fi
validate_reset_database_target
warn "即将重置 PostgreSQL 数据库:会删除订单、任务、后台用户、审计日志和所有迁移记录。"
warn "不会删除 apps/backend/data 下的平台 JSON 配置,也不会删除 Caddy 证书卷。"
if [[ "${RESET_DB_CONFIRM}" == "1" ]]; then
warn "检测到 RESET_DB_CONFIRM=1 或 --yes,跳过交互确认。"
return
fi
if [[ ! -t 0 ]]; then
fail "当前不是交互式终端。若确认要重置数据库,请执行:RESET_DB_CONFIRM=1 bash deploy/ubuntu-deploy.sh --reset-db"
fi
local answer
printf '请输入 RESET 确认重置数据库:'
read -r answer
[[ "${answer}" == "RESET" ]] || fail "未确认重置数据库,已停止。"
}
ensure_data_dir() {
mkdir -p "${BACKEND_DATA_DIR}"
@@ -121,6 +197,65 @@ build_images() {
docker compose build web || fail "Web 镜像构建失败。"
}
resolve_compose_project_name() {
local project_name
project_name="$(read_env_value COMPOSE_PROJECT_NAME || true)"
if [[ -z "${project_name}" ]]; then
project_name="$(basename "${PROJECT_ROOT}")"
fi
printf '%s\n' "${project_name}"
}
resolve_postgres_volume_name() {
local container_id volume_name project_name
container_id="$(docker compose ps -aq postgres 2>/dev/null | head -n 1 || true)"
if [[ -n "${container_id}" ]]; then
volume_name="$(
docker inspect -f '{{range .Mounts}}{{if eq .Destination "/var/lib/postgresql/data"}}{{if eq .Type "volume"}}{{.Name}}{{end}}{{end}}{{end}}' "${container_id}" 2>/dev/null || true
)"
if [[ -n "${volume_name}" ]]; then
printf '%s\n' "${volume_name}"
return
fi
fi
volume_name="$(
docker compose volumes 2>/dev/null \
| awk '$2 ~ /(^|_)postgres_data$/ { print $2; exit }' || true
)"
if [[ -n "${volume_name}" ]]; then
printf '%s\n' "${volume_name}"
return
fi
project_name="$(resolve_compose_project_name)"
printf '%s_postgres_data\n' "${project_name}"
}
reset_database() {
if [[ "${RESET_DB}" != "true" ]]; then
return
fi
local volume_name
volume_name="$(resolve_postgres_volume_name)"
warn "开始重置数据库,将删除 Docker volume${volume_name}"
docker compose stop web backend postgres >/dev/null 2>&1 || true
docker compose rm -f -s postgres >/dev/null 2>&1 || true
if docker volume inspect "${volume_name}" >/dev/null 2>&1; then
docker volume rm "${volume_name}" >/dev/null || fail "删除 PostgreSQL 数据卷失败:${volume_name}"
log "已删除 PostgreSQL 数据卷:${volume_name}"
return
fi
warn "未找到 PostgreSQL 数据卷:${volume_name},将按空库继续部署。"
}
wait_for_service() {
local service="$1"
local label="$2"
@@ -204,6 +339,7 @@ deploy_stack() {
check_compose_config
pull_base_images
build_images
reset_database
start_postgres
run_database_migrations
restart_backend
@@ -257,7 +393,7 @@ print_diagnostics() {
if printf '%s\n' "${backend_logs}" | grep -q 'password authentication failed for user "postgres"'; then
warn "检测到 PostgreSQL 密码认证失败。通常是 postgres_data 已用旧密码初始化,而 .env 改成了新密码。"
warn "无生产数据时可执行:docker compose down -v && bash deploy/ubuntu-deploy.sh"
warn "无生产数据时可执行:RESET_DB_CONFIRM=1 bash deploy/ubuntu-deploy.sh --reset-db"
warn "需要保留数据时,请进入 postgres 容器用当前 .env 的 POSTGRES_PASSWORD 修改数据库用户密码。"
fi
@@ -268,11 +404,14 @@ print_diagnostics() {
}
main() {
parse_args "$@"
cd "${PROJECT_ROOT}"
ensure_docker
ensure_env_file
validate_env_file
confirm_reset_database
ensure_data_dir
deploy_stack
wait_for_health