diff --git a/.github/workflows/build-service-images.yml b/.github/workflows/build-service-images.yml index 80c7408..36546b7 100644 --- a/.github/workflows/build-service-images.yml +++ b/.github/workflows/build-service-images.yml @@ -51,9 +51,10 @@ on: push: branches: [ main ] paths: + - "account/**" - "dashboard/**" - "rag-server/**" - - "account/**" + - "xcontrol-init/**" permissions: contents: read @@ -82,9 +83,10 @@ jobs: strategy: matrix: service: + - { name: account, workdir: account } - { name: dashboard, workdir: dashboard } - { name: rag-server, workdir: rag-server } - - { name: account, workdir: account } + - { name: xcontrol-init, workdir: xcontrol-init } steps: # ------------------------------------------------------------- @@ -172,8 +174,9 @@ jobs: matrix: service: - { name: dashboard, workdir: dashboard } - - { name: rag-server, workdir: rag-server } - { name: account, workdir: account } + - { name: rag-server, workdir: rag-server } + - { name: xcontrol-init, workdir: xcontrol-init } steps: # ------------------------------------------------------------- diff --git a/xcontrol-init/Dockerfile b/xcontrol-init/Dockerfile new file mode 100644 index 0000000..0895c69 --- /dev/null +++ b/xcontrol-init/Dockerfile @@ -0,0 +1,65 @@ +# ============================================================ +# Stage 1: Build createadmin (Go tool) +# ============================================================ +FROM golang:1.25 AS builder + +WORKDIR /workspace + +# ------------------------------------------------------------ +# 下载依赖(仅 account 模块的依赖即可满足 createadmin) +# ------------------------------------------------------------ +COPY account/go.mod account/go.sum ./account/ +RUN cd account && go mod download + +# ------------------------------------------------------------ +# 复制 account 模块源码(只复制一次更高效) +# ------------------------------------------------------------ +COPY account ./account + +# ------------------------------------------------------------ +# 构建 createadmin 可执行文件 +# ------------------------------------------------------------ +RUN cd account && \ + CGO_ENABLED=0 GOOS=linux go build -o /createadmin ./cmd/createadmin/main.go + + + +# ============================================================ +# Stage 2: Runtime Image +# 用于作为 Kubernetes Init Container 使用 +# ============================================================ +FROM debian:12-slim + +# ------------------------------------------------------------ +# 安装 PostgreSQL 客户端、证书等最小运行依赖 +# ------------------------------------------------------------ +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + postgresql-client \ + ca-certificates \ + curl \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +# ------------------------------------------------------------ +# 拷贝 schema 文件到统一位置 +# ------------------------------------------------------------ +COPY account/sql /app/schemas/account +COPY rag-server/sql /app/schemas/rag + +# ------------------------------------------------------------ +# 拷贝 createadmin 工具 +# ------------------------------------------------------------ +COPY --from=builder /createadmin /usr/local/bin/createadmin + +# ------------------------------------------------------------ +# 拷贝初始化脚本(init-db.sh) +# ------------------------------------------------------------ +COPY xcontrol-init/scripts/init-db.sh /usr/local/bin/init-db.sh +RUN chmod +x /usr/local/bin/init-db.sh + +# ------------------------------------------------------------ +# 设置入口点 +# ------------------------------------------------------------ +ENTRYPOINT ["/usr/local/bin/init-db.sh"] diff --git a/xcontrol-init/scripts/init-db.sh b/xcontrol-init/scripts/init-db.sh new file mode 100644 index 0000000..63ce2bf --- /dev/null +++ b/xcontrol-init/scripts/init-db.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +set -e + +echo "== XControl Init ==" + +# 必须的环境变量 +: "${DB_HOST:?}" +: "${DB_PORT:?}" +: "${DB_NAME:?}" +: "${DB_USER:?}" +: "${DB_PASS:?}" +: "${SCHEMA_DIR:?}" + +ADMIN_USER="${ADMIN_USER:-postgres}" +ADMIN_PASS="${ADMIN_PASS:-postgres}" + +APP_DSN="postgres://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=disable" +ADMIN_DSN="postgres://${ADMIN_USER}:${ADMIN_PASS}@${DB_HOST}:${DB_PORT}/postgres" + +# 基础函数 +admin_sql() { PGPASSWORD="$ADMIN_PASS" psql "$ADMIN_DSN" -Atc "$1"; } +app_sql() { PGPASSWORD="$DB_PASS" psql "$APP_DSN" -Atc "$1"; } + +echo "-- 检查用户 $DB_USER" +if admin_sql "SELECT 1 FROM pg_roles WHERE rolname='${DB_USER}'" | grep -q 1; then + echo "✓ 用户已存在" +else + admin_sql "CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASS}'" + echo "✓ 用户已创建" +fi + +echo "-- 检查数据库 $DB_NAME" +if admin_sql "SELECT 1 FROM pg_database WHERE datname='${DB_NAME}'" | grep -q 1; then + echo "✓ 数据库已存在" +else + admin_sql "CREATE DATABASE ${DB_NAME} OWNER ${DB_USER}" + echo "✓ 数据库已创建" +fi + +echo "-- 修复 public schema 权限" +app_sql "ALTER SCHEMA public OWNER TO ${DB_USER}" || true + +echo "-- 执行所有 schema.sql" + +for f in $(find "$SCHEMA_DIR" -name schema.sql | sort); do + echo ">>> 应用 $f" + PGPASSWORD="$DB_PASS" psql "$APP_DSN" -f "$f" +done + +echo "✓ 所有 schema.sql 执行完毕" + +# 创建超级管理员(可选) +if [ -n "${SUPERADMIN_USERNAME:-}" ] && [ -n "${SUPERADMIN_PASSWORD:-}" ]; then + echo "-- 检查超级管理员 ${SUPERADMIN_USERNAME}" + + EXISTS=$(app_sql \ + "SELECT 1 FROM accounts WHERE username='${SUPERADMIN_USERNAME}' LIMIT 1;" + ) + + if [ "$EXISTS" = "1" ]; then + echo "✓ 超管已存在" + else + echo "-- 创建超级管理员 ${SUPERADMIN_USERNAME}" + createadmin \ + --driver postgres \ + --dsn "$APP_DSN" \ + --username "$SUPERADMIN_USERNAME" \ + --password "$SUPERADMIN_PASSWORD" \ + --email "${SUPERADMIN_EMAIL:-admin@localhost}" + echo "✓ 超管创建完成" + fi +fi + +echo "== XControl Init 完成 =="