# XXX huijutec.cn / QNAP QTS 直接部署版。 # XXX 本文件已按 /share/Container/tuwen_system_v2、https://sstwbg.huijutec.cn、 # XXX 192.168.31.7:7893 代理和 frpc 公网映射预置,复制到 QTS Container Station 后可直接运行。 services: tuwen_db: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_DB: surclaw POSTGRES_USER: surclaw POSTGRES_PASSWORD: surclaw_dev_password volumes: - /share/Container/tuwen_system_v2/data/postgres:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U surclaw -d surclaw"] interval: 10s timeout: 5s retries: 10 tuwen_api: # XXX huijutec 专用镜像 tag;减少 QTS 残留旧镜像导致配置未生效的概率。 image: surclaw/tuwen-api:huijutec-20260511 build: # XXX QTS/Container Station 可能不在项目根目录执行 Compose,所以这里必须写绝对路径。 context: /share/Container/tuwen_system_v2 dockerfile: Dockerfile.server args: HTTP_PROXY: http://192.168.31.7:7893 HTTPS_PROXY: http://192.168.31.7:7893 NO_PROXY: localhost,127.0.0.1,192.168.31.0/24,tuwen_db,tuwen_api,tuwen_web,api,db,web restart: unless-stopped networks: default: aliases: # XXX nginx.conf 中 /api 固定代理到 http://api:3100,必须保留 api 别名。 - api depends_on: tuwen_db: condition: service_healthy ports: - "4102:3100" volumes: - /share/Container/tuwen_system_v2/data/uploads:/app/uploads environment: NODE_ENV: production PORT: 3100 API_PORT: 3100 DATABASE_URL: postgresql://surclaw:surclaw_dev_password@tuwen_db:5432/surclaw?schema=public CORS_ORIGIN: https://sstwbg.huijutec.cn,http://192.168.31.5:4002,http://localhost:4002,https://localhost:4443 SESSION_SECRET: c834e27ad2fad348ef7dd3d43d295d1943c18fa8e5a3296ddca9b4a0db650819 SESSION_COOKIE_SECURE: "true" TRUST_PROXY: "true" FILE_STORAGE_DIR: /app/uploads API_BODY_LIMIT: 100mb RUN_DB_MIGRATIONS: "true" RUN_DB_SEED: "true" DOCKER_STARTUP_RETRIES: 30 DOCKER_STARTUP_RETRY_DELAY: 2 HTTP_PROXY: http://192.168.31.7:7893 HTTPS_PROXY: http://192.168.31.7:7893 http_proxy: http://192.168.31.7:7893 https_proxy: http://192.168.31.7:7893 NO_PROXY: localhost,127.0.0.1,192.168.31.0/24,tuwen_db,tuwen_api,tuwen_web,api,db,web healthcheck: # XXX 使用 127.0.0.1,规避部分 NAS 固件中 localhost 优先解析 IPv6 的问题。 test: ["CMD-SHELL", "node -e \"fetch('http://127.0.0.1:3100/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""] interval: 10s timeout: 5s retries: 12 start_period: 20s tuwen_web: # XXX huijutec 专用镜像 tag;nginx.conf 更新后必须重新构建出这个新 web 镜像。 image: surclaw/tuwen-web:huijutec-20260511 build: # XXX QTS/Container Station 可能不在项目根目录执行 Compose,所以这里必须写绝对路径。 context: /share/Container/tuwen_system_v2 dockerfile: Dockerfile args: HTTP_PROXY: http://192.168.31.7:7893 HTTPS_PROXY: http://192.168.31.7:7893 NO_PROXY: localhost,127.0.0.1,192.168.31.0/24,tuwen_db,tuwen_api,tuwen_web,api,db,web restart: unless-stopped depends_on: tuwen_api: condition: service_healthy ports: - "4002:80" - "4443:443" environment: APP_URL: https://sstwbg.huijutec.cn healthcheck: test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1/ || exit 1"] interval: 10s timeout: 5s retries: 6 tuwen_frpc: # XXX QTS/Container Station 版默认启动 frpc,启动后 FRP 面板应显示 TuWen_System_V2 Online。 # XXX 为避免 QTS 把 frpc 配置文件挂载路径改到应用临时目录,这里不再挂载 frpc.toml, # XXX 而是在容器启动时自动写入 /tmp/frpc.toml。 image: snowdreamtech/frpc:latest restart: unless-stopped entrypoint: ["/bin/sh"] command: - -c - | cat > /tmp/frpc.toml <<'EOF' serverAddr = "82.157.255.195" serverPort = 7000 auth.method = "token" auth.token = "en.xjtu.edu.cn" transport.poolCount = 5 transport.heartbeatTimeout = -1 [[proxies]] name = "TuWen_System_V2" type = "tcp" localIP = "tuwen_web" localPort = 80 remotePort = 4002 EOF exec frpc -c /tmp/frpc.toml depends_on: tuwen_web: condition: service_healthy