#!/usr/bin/env bash # 首次部署:启动 Docker 栈、执行迁移,并在缺少 admin 时写入生产默认数据。 set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=scripts/deploy-lib.sh source "$SCRIPT_DIR/deploy-lib.sh" NO_BUILD=false RUN_SEED=true INIT_DB=false SKIP_BACKUP=false ALLOW_DEFAULT_SECRETS=false IMAGE_TAR="" usage() { cat <<'EOF' 用法: scripts/deploy-first.sh [选项] 默认流程: 1. 检查 .env.docker 2. 启动 postgres / redis 3. 构建 api / player / admin 镜像 4. 执行 prisma migrate deploy 5. 启动全栈容器 6. 如果数据库中没有 admin,执行一次生产 seed 选项: --no-build 不构建镜像,直接使用服务器已有镜像 --images PATH 先 docker load 指定镜像 tar,并自动跳过本机构建 --tag TAG 使用指定镜像 tag,并写入 .env.docker 的 IMAGE_TAG --no-seed 不执行生产 seed --init-db 调用 scripts/prod-init-db.sh 清空业务数据并初始化生产数据,仅限全新库或明确重置 --skip-backup 与 --init-db 一起使用,跳过 prod-init-db 的备份 --allow-default-secrets 允许 .env.docker 使用示例密钥,仅测试环境使用 -h, --help 显示帮助 示例: ./scripts/deploy-first.sh ./scripts/deploy-first.sh --images thebet365-images-v1.2.3.tar --tag v1.2.3 ./scripts/deploy-first.sh --no-build ./scripts/deploy-first.sh --init-db EOF } while [ $# -gt 0 ]; do case "$1" in --no-build) NO_BUILD=true shift ;; --images) IMAGE_TAR="${2:?缺少 --images 参数值}" NO_BUILD=true shift 2 ;; --tag) set_deploy_image_tag "${2:?缺少 --tag 参数值}" shift 2 ;; --no-seed) RUN_SEED=false shift ;; --init-db) INIT_DB=true RUN_SEED=false shift ;; --skip-backup) SKIP_BACKUP=true shift ;; --allow-default-secrets) ALLOW_DEFAULT_SECRETS=true shift ;; -h|--help) usage exit 0 ;; *) die "未知参数: $1" ;; esac done cd "$ROOT" require_docker ensure_env_file || exit 1 validate_prod_env "$ALLOW_DEFAULT_SECRETS" if [ -n "$IMAGE_TAR" ] && [ -z "${DEPLOY_IMAGE_TAG:-}" ]; then inferred_tag="$(infer_image_tag_from_tar "$IMAGE_TAR")" if [ -n "$inferred_tag" ]; then set_deploy_image_tag "$inferred_tag" log "从镜像包文件名推断 tag: $inferred_tag" fi fi if [ -n "$IMAGE_TAR" ]; then load_image_tar "$IMAGE_TAR" fi start_infra if [ "$NO_BUILD" = false ]; then build_app_images else log "跳过镜像构建,使用服务器已有镜像" require_images_for_current_tag fi run_prisma_migrations if [ "$INIT_DB" = false ] && [ "$RUN_SEED" = true ]; then seed_production_if_missing_admin fi log "启动 api / player / admin" compose up -d api player admin wait_for_stack_ready if [ "$INIT_DB" = true ]; then init_args=() if [ "$SKIP_BACKUP" = true ]; then init_args+=(--skip-backup) fi log "执行生产初始化:这会清空业务数据" CONFIRM=YES "$ROOT/scripts/prod-init-db.sh" "${init_args[@]}" compose restart api wait_for_service_health api 180 fi show_prisma_status compose ps persist_image_tag record_release_state "first-deploy" print_stack_urls