# ============================================ # FLNXI素材库 - 私有化生产配置 # 默认使用内置 PostgreSQL + MinIO,也可通过 .env 切换外部数据库或对象存储。 # 主应用从版本化 Registry 镜像启动,客户现场无需源码。 # ============================================ # Registry 项目结构: # - flnxi/runtime:PostgreSQL、MinIO 等运行依赖镜像 # - flnxi/material 或 flnxi/material-dev:素材系统正式版 / 测试版镜像 # 客户交付必须在 .env 中显式填写 APP_IMAGE,避免误拉旧仓库或 latest。 # ============================================ services: # PostgreSQL 数据库 postgres: # 可由 .env 覆盖为私有 Registry runtime 镜像;默认走 Docker Hub 官方镜像。 image: ${POSTGRES_IMAGE:-postgres:15-alpine} container_name: ${POSTGRES_CONTAINER_NAME:-flnxi-postgres} restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} POSTGRES_DB: ${POSTGRES_DB:-flnxi} POSTGRES_INITDB_ARGS: "--encoding=UTF-8" volumes: - postgres_data:/var/lib/postgresql/data networks: - app-network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"] interval: 10s timeout: 5s retries: 5 # MinIO 对象存储 # 使用特定版本号确保稳定性(符合项目宗旨:稳定性优先) minio: # 可由 .env 覆盖为私有 Registry runtime 镜像;默认走官方镜像。 image: ${MINIO_IMAGE:-minio/minio:RELEASE.2025-04-22T22-12-26Z} container_name: ${MINIO_CONTAINER_NAME:-flnxi-minio} restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:?MINIO_ROOT_USER is required} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?MINIO_ROOT_PASSWORD is required} volumes: - minio_data:/data ports: - "${MINIO_API_BIND_HOST:-0.0.0.0}:${MINIO_API_PORT:-9000}:9000" - "${MINIO_CONSOLE_BIND_HOST:-127.0.0.1}:${MINIO_CONSOLE_PORT:-9001}:9001" networks: - app-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 3 # MinIO 初始化服务(创建bucket) minio-init: # mc 客户端用于初始化桶;离线或客户现场可在 .env 中覆盖为私有 Registry 镜像。 image: ${MINIO_MC_IMAGE:-minio/mc:RELEASE.2025-04-16T18-13-26Z} container_name: ${MINIO_INIT_CONTAINER_NAME:-flnxi-minio-init} environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:?MINIO_ROOT_USER is required} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?MINIO_ROOT_PASSWORD is required} S3_BUCKET: ${S3_BUCKET:-flnxi-materials} S3_SET_ACL: ${S3_SET_ACL:-0} S3_PUBLIC_READ: ${S3_PUBLIC_READ:-0} depends_on: minio: condition: service_healthy entrypoint: | /bin/sh -c ' set -e; sleep 5; mc alias set myminio http://minio:9000 "$${MINIO_ROOT_USER}" "$${MINIO_ROOT_PASSWORD}"; mc mb "myminio/$${S3_BUCKET}" --ignore-existing; PUBLIC_READ="$$(printf "%s" "$${S3_SET_ACL:-0}:$${S3_PUBLIC_READ:-0}" | tr "[:upper:]" "[:lower:]")"; case "$$PUBLIC_READ" in 1:*|true:*|yes:*|*:1|*:true|*:yes) echo "WARNING: S3 public read compatibility is enabled; bucket anonymous download will be allowed"; mc anonymous set download "myminio/$${S3_BUCKET}"; ;; *) mc anonymous set none "myminio/$${S3_BUCKET}"; echo "MinIO bucket anonymous access disabled"; ;; esac; echo "MinIO bucket created and configured successfully"; ' networks: - app-network # 主应用(Pro版 - 从私有镜像仓库拉取,需 token) app: # 客户交付必须显式填写完整 APP_IMAGE,例如: # APP_IMAGE=registry.example.com/flnxi/material/flnxi-material:1.0.1 image: ${APP_IMAGE:?APP_IMAGE is required, for example registry.example.com/flnxi/material/flnxi-material:1.0.1} container_name: ${APP_CONTAINER_NAME:-flnxi-material} restart: unless-stopped ports: - "${APP_PORT:-4320}:3000" # 使用 env_file 自动读取 .env 文件中的所有环境变量(包括 DATABASE_URL) # 这样 Docker Compose 会自动处理所有变量,无需手动拼接 env_file: - .env environment: # 注意: # - SERVER_IP 必须在 .env 中配置为「本机在局域网中的访问 IP」,例如:192.168.41.144 - NODE_ENV=production - APP_PUBLIC_URL=${APP_PUBLIC_URL:?APP_PUBLIC_URL is required} # DATABASE_URL 从 .env 文件自动读取;未配置时按同一份 .env 中的数据库变量拼接 - DATABASE_URL=${DATABASE_URL:-postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-flnxi}} - DATABASE_DRIVER=node - STORAGE_PROVIDER=s3 - S3_ENDPOINT=${S3_ENDPOINT:-http://minio:9000} - S3_BUCKET=${S3_BUCKET:-flnxi-materials} - S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID:-${MINIO_ROOT_USER}} - S3_SECRET_ACCESS_KEY=${S3_SECRET_ACCESS_KEY:-${MINIO_ROOT_PASSWORD}} - S3_REGION=${S3_REGION:-us-east-1} # 对外访问 MinIO 的地址(供前端和分享链接使用),必须是局域网 / 公网可访问的 IP 或域名 # 这里不再默认 127.0.0.1,避免在 NAS 等环境下写死 localhost - S3_PUBLIC_DOMAIN=${S3_PUBLIC_DOMAIN:-http://${SERVER_IP}:${MINIO_API_PORT:-9000}/${S3_BUCKET:-flnxi-materials}} - S3_ENABLE_PATH_STYLE=${S3_ENABLE_PATH_STYLE:-1} - S3_SET_ACL=${S3_SET_ACL:-0} - S3_PREVIEW_URL_EXPIRE_IN=7200 - S3_FILE_PATH=materials/ - NEXT_PUBLIC_S3_FILE_PATH=materials/ # NextAuth 的外部访问地址,从 .env 中注入(不在这里拼接,以免 SERVER_IP 为空时产生 http://:4320) # 客户首装或部署脚本应写入 NEXTAUTH_URL,例如:http://192.168.41.144:4320 - NEXTAUTH_URL=${NEXTAUTH_URL} - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:?NEXTAUTH_SECRET is required} - LICENSE_SERVER_URL=${LICENSE_SERVER_URL:?LICENSE_SERVER_URL is required} - LICENSE_PROJECT_CODE=${LICENSE_PROJECT_CODE:?LICENSE_PROJECT_CODE is required} - LICENSE_REQUEST_SIGNING_SECRET=${LICENSE_REQUEST_SIGNING_SECRET:?LICENSE_REQUEST_SIGNING_SECRET is required} - LICENSE_PUBLIC_KEY=${LICENSE_PUBLIC_KEY:?LICENSE_PUBLIC_KEY is required} - LOCAL_ENCRYPTION_KEY=${LOCAL_ENCRYPTION_KEY:?LOCAL_ENCRYPTION_KEY is required} - PAID_CORE_MODULE_URL=${PAID_CORE_MODULE_URL:-http://flnxi-module-paid-core:8787} - MODULE_RUNTIME_STATUS_TOKEN=${MODULE_RUNTIME_STATUS_TOKEN:-} # 初始管理员账号(供 /api/system/init 使用) - INIT_ADMIN_EMAIL=${INIT_ADMIN_EMAIL:-admin@local.flnxi} - INIT_ADMIN_PASSWORD=${INIT_ADMIN_PASSWORD:-} - SYSTEM_INIT_TOKEN=${SYSTEM_INIT_TOKEN:-} volumes: - ./uploads:/app/uploads - ./data:/app/data depends_on: postgres: condition: service_healthy minio: condition: service_healthy minio-init: condition: service_completed_successfully networks: - app-network healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3000/api/health"] interval: 30s timeout: 10s retries: 3 volumes: postgres_data: name: ${POSTGRES_VOLUME_NAME:-flnxi-postgres-data} driver: local minio_data: name: ${MINIO_VOLUME_NAME:-flnxi-minio-data} driver: local networks: app-network: name: ${APP_NETWORK_NAME:-flnxi-app-network} driver: bridge