Files
order_site/deploy/ubuntu-deploy.sh
T
2026-05-26 16:54:30 +08:00

126 lines
3.2 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
# Ubuntu 服务器一键部署脚本。
# 用法:bash deploy/ubuntu-deploy.sh
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ENV_FILE="${PROJECT_ROOT}/.env"
ENV_EXAMPLE="${PROJECT_ROOT}/.env.server.example"
BACKEND_DATA_DIR="${PROJECT_ROOT}/apps/backend/data"
BACKEND_CONTAINER_UID=1001
BACKEND_CONTAINER_GID=1001
HEALTH_URL=""
log() {
printf '\033[1;34m[deploy]\033[0m %s\n' "$*"
}
warn() {
printf '\033[1;33m[deploy]\033[0m %s\n' "$*"
}
fail() {
printf '\033[1;31m[deploy]\033[0m %s\n' "$*" >&2
exit 1
}
read_env_value() {
local key="$1"
awk -F= -v key="${key}" '
$0 !~ /^[[:space:]]*#/ && $1 == key {
value = substr($0, index($0, "=") + 1)
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
gsub(/^"|"$/, "", value)
gsub(/^'\''|'\''$/, "", value)
print value
exit
}
' "${ENV_FILE}"
}
ensure_docker() {
command -v docker >/dev/null 2>&1 || fail "未找到 docker,请先在 Ubuntu 上安装 Docker Engine。"
docker compose version >/dev/null 2>&1 || fail "未找到 docker compose 插件,请安装 Docker Compose plugin。"
command -v curl >/dev/null 2>&1 || fail "未找到 curl,请先安装:sudo apt-get update && sudo apt-get install -y curl"
}
ensure_env_file() {
if [[ -f "${ENV_FILE}" ]]; then
return
fi
cp "${ENV_EXAMPLE}" "${ENV_FILE}"
fail "已生成 .env,请先编辑真实域名、数据库密码、后台账号和密钥后再重新执行。"
}
validate_env_file() {
if grep -nE 'change-me|your-domain|example\.com' "${ENV_FILE}" >/tmp/order-site-env-placeholders.txt; then
cat /tmp/order-site-env-placeholders.txt >&2
fail ".env 仍包含示例占位值,请替换后再部署。"
fi
local site_addr
site_addr="$(read_env_value CADDY_SITE_ADDR)"
[[ -n "${site_addr}" ]] || fail ".env 缺少 CADDY_SITE_ADDR。"
HEALTH_URL="${site_addr%/}/health/ready"
}
ensure_data_dir() {
mkdir -p "${BACKEND_DATA_DIR}"
if [[ "$(id -u)" == "0" ]]; then
chown -R "${BACKEND_CONTAINER_UID}:${BACKEND_CONTAINER_GID}" "${BACKEND_DATA_DIR}"
return
fi
if command -v sudo >/dev/null 2>&1; then
sudo chown -R "${BACKEND_CONTAINER_UID}:${BACKEND_CONTAINER_GID}" "${BACKEND_DATA_DIR}"
return
fi
warn "未找到 sudo,跳过目录属主调整。若后端无法写入日志或配置,请执行:"
warn "sudo chown -R ${BACKEND_CONTAINER_UID}:${BACKEND_CONTAINER_GID} ${BACKEND_DATA_DIR}"
}
deploy_stack() {
log "拉取基础镜像"
docker compose pull --ignore-buildable
log "构建并启动服务"
docker compose up -d --build
}
wait_for_health() {
log "等待服务健康检查:${HEALTH_URL}"
for _ in $(seq 1 60); do
if curl -fsS "${HEALTH_URL}" >/dev/null 2>&1; then
log "服务已就绪"
return
fi
sleep 2
done
docker compose ps
warn "健康检查暂未通过,最近后端日志如下:"
docker compose logs --tail=80 backend
fail "部署已启动但健康检查未通过,请根据日志排查。"
}
main() {
cd "${PROJECT_ROOT}"
ensure_docker
ensure_env_file
validate_env_file
ensure_data_dir
deploy_stack
wait_for_health
log "部署完成"
docker compose ps
}
main "$@"