# SkillHub 一站式本地开发编排 # # ⚠ 仅用于开发自验证场景(本地快速拉起全套服务联调)。 # 生产环境请使用独立部署的 MinIO/OBS、或 K8s 方案(见 docs/zh/3. 安装指导/)。 # 为兼容 Linux(backend 经 host-gateway 访问 MinIO),S3 API 端口绑定 0.0.0.0, # 请勿在不可信网络环境运行。 # # 用法(在仓库根目录执行): # 1. 确保根目录有 .env 文件(可从 .env.example 复制) # 2. (可选)在 hosts 文件添加一行以支持文件下载预签名 URL: # Windows: C:\Windows\System32\drivers\etc\hosts # Linux/Mac: /etc/hosts # 追加: 127.0.0.1 minio # 3. docker compose -f docker/docker-compose.yml --env-file .env up -d --build # 4. 访问 http://localhost:9002 # # 后续运维命令同样需带 -f docker/docker-compose.yml --env-file .env 前缀, # 如:docker compose -f docker/docker-compose.yml --env-file .env ps # # 健康检查: # curl http://localhost:8100/api/health name: skillhub services: # ── MySQL ───────────────────────────────────────────────────────────── # 首次启动通过 docker/mysql-init/01-init.sh 执行 sql/baseline/ DDL, # 再按版本执行 sql/incremental/ 的 B001–B005。 # backend 启动时 create_all 只补尚未存在的表,不会给已有表加列。 mysql: image: mysql:8.0 restart: unless-stopped command: --character-set-server=utf8mb4 --collation-server=utf8mb4_0900_ai_ci environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:-root} MYSQL_DATABASE: ${STORE_DB_NAME:-openjiuwen_market} MYSQL_USER: skillhub MYSQL_PASSWORD: ${DB_PASSWORD:-root} ports: # 宿主机端口独立于 DB_PORT(DB_PORT=3306 是 backend 连库端口,不应用于宿主机映射) - "127.0.0.1:${MYSQL_HOST_PORT:-3001}:3306" volumes: - mysql-data:/var/lib/mysql - ../sql:/sql:ro - ./mysql-init:/docker-entrypoint-initdb.d:ro healthcheck: test: ["CMD", "mysql", "-uroot", "-p${DB_PASSWORD:-root}", "-e", "SELECT 1"] interval: 5s timeout: 5s retries: 20 start_period: 40s # ── Redis ───────────────────────────────────────────────────────────── # 用于 OAuth session、索引热更新广播、Playground 状态 redis: image: redis:7-alpine restart: unless-stopped ports: # 宿主机端口独立于 REDIS_PORT(REDIS_PORT=6379 是 backend 连接端口,不应用于宿主机映射) - "127.0.0.1:${REDIS_HOST_PORT:-6379}:6379" volumes: - redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 10 # ── MinIO (S3 兼容对象存储) ────────────────────────────────────────── # 9000 = S3 API(backend 上传/下载 + 浏览器预签名 URL) # 9001 = 管理控制台(仅本机) # 注:S3 API 端口绑定 0.0.0.0,使 backend 经 host-gateway 访问时在 Linux 上也能连通 # (127.0.0.1 绑定会拒绝来自 host-gateway 的非 loopback 连接)。本编排仅用于开发自验证, # 生产环境请使用独立部署的 MinIO/OBS 或 K8s 方案。 minio: image: minio/minio:RELEASE.2025-09-07T16-13-09Z restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MARKET_S3_ACCESS_KEY:-minioadmin} MINIO_ROOT_PASSWORD: ${MARKET_S3_SECRET_KEY:-minioadmin} ports: - "0.0.0.0:${MINIO_API_PORT:-3003}:9000" - "127.0.0.1:${MINIO_CONSOLE_PORT:-9001}:9001" volumes: - minio-data:/data # 一次性初始化容器:等待 MinIO 就绪后创建 Bucket # 不依赖 minio healthcheck(mc ready 在某些镜像中不可用), # 改为 service_started + entrypoint 内重试循环 minio-init: image: minio/mc:RELEASE.2025-08-13T08-35-41Z depends_on: minio: condition: service_started environment: MINIO_ROOT_USER: ${MARKET_S3_ACCESS_KEY:-minioadmin} MINIO_ROOT_PASSWORD: ${MARKET_S3_SECRET_KEY:-minioadmin} MARKET_BUCKET_NAME: ${MARKET_BUCKET_NAME:-openjiuwen-market-test} entrypoint: - /bin/sh - -c - | until mc alias set local http://minio:9000 "$$MINIO_ROOT_USER" "$$MINIO_ROOT_PASSWORD" > /dev/null 2>&1; do echo 'waiting for minio...'; sleep 2; done && mc mb --ignore-existing "local/$$MARKET_BUCKET_NAME" && echo 'bucket ready' # ── Backend (FastAPI marketplace) ──────────────────────────────────── backend: build: context: .. dockerfile: docker/Dockerfile.skillhub-backend args: INDEX_URL: ${PIP_INDEX_URL:-https://pypi.org/simple} TRUSTED_HOST: ${PIP_TRUSTED_HOST:-pypi.org} APT_MIRROR: ${APT_MIRROR:-} env_file: ../.env restart: unless-stopped environment: # 覆盖 .env 中的本地开发值,改为 Docker 内部服务名 DB_HOST: mysql DB_PORT: "3306" DB_USER: skillhub REDIS_HOST: redis REDIS_PORT: "6379" STORE_HOST: "0.0.0.0" STORE_PORT: "8100" MARKET_DEBUG: ${MARKET_DEBUG:-false} # 使用宿主机映射端口,使预签名 URL 对浏览器可用(需在 hosts 添加 127.0.0.1 minio) # 端口跟随 MINIO_API_PORT,改端口时预签名 URL 自动同步 MARKET_S3_ENDPOINT: http://minio:${MINIO_API_PORT:-3003} extra_hosts: - "minio:host-gateway" ports: - "127.0.0.1:${STORE_PORT:-8100}:8100" depends_on: mysql: condition: service_healthy redis: condition: service_healthy minio-init: condition: service_completed_successfully healthcheck: test: ["CMD", "python", "-c", "import urllib.request as r; r.urlopen('http://127.0.0.1:8100/api/health', timeout=2).read()"] interval: 15s timeout: 5s start_period: 30s retries: 10 # ── Frontend (React + Nginx) ───────────────────────────────────────── # Nginx 将 /api/ 反代到 backend 容器 frontend: build: context: .. dockerfile: docker/Dockerfile.skillhub-frontend environment: BACKEND_URL: backend BACKEND_PORT: "8100" ports: - "127.0.0.1:${FRONTEND_PORT:-9002}:9002" depends_on: backend: condition: service_healthy volumes: mysql-data: redis-data: minio-data: