# 深学在线 · 本地开发基础设施 # # 用法: # cd deploy # copy .env.example .env (首次) # docker compose up -d # # ⚠️ nginx 挂的是 H5 **构建产物**,所以第一次起它之前要先: # cd frontend-mp && pnpm build:h5 # (产物不入库;目录不存在时 docker 会建一个空目录 → 页面 404,容器却一切正常) # # ⚠️ 容器名统一加 xt- 前缀,端口刻意避开 55432 / 6379 # (本机已有其他项目的 pg-verify 与 redis-local 在跑,不要动它们) # # 对象存储:用**七牛云**,这里不起容器。 # 材料原图与规范件存七牛(空间 tools-matrix,私有 → 下载走签名链接), # 由后端用官方 SDK 直连,不走 S3 协议。 # 曾经起过一个 MinIO 备用("本地/生产走同一套 S3 接口"),但代码最终走的是七牛 SDK, # 那个容器从来没被连过 —— 留着只会让人以为"本地还有个对象存储要用",所以删掉了。 # 本地开发也不需要它:provider=local 时文件落在 backend/data/uploads。 name: xiaotutongxue services: # ── PostgreSQL 16 ───────────────────────────────── pg: image: postgres:16-alpine container_name: xt-pg restart: unless-stopped environment: POSTGRES_DB: ${PG_DB:-filldb} POSTGRES_USER: ${PG_USER:-fill} POSTGRES_PASSWORD: ${PG_PASSWORD:-fill_dev_pwd} # 中文排序与大小写:用 C 排序 + UTF8,避免 locale 差异导致索引行为不一致 POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C" TZ: Asia/Shanghai ports: - "${PG_PORT:-5432}:5432" volumes: - pg-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${PG_USER:-fill} -d ${PG_DB:-filldb}"] interval: 5s timeout: 3s retries: 12 start_period: 10s command: - postgres # 超大图处理是内存密集的,DB 侧保留默认即可,但把慢查询记下来 - -c - log_min_duration_statement=1000 - -c - timezone=Asia/Shanghai # ── Redis 7 ─────────────────────────────────────── redis: image: redis:7-alpine container_name: xt-redis restart: unless-stopped ports: - "${REDIS_PORT:-16379}:6379" volumes: - redis-data:/data command: - redis-server - --appendonly - "yes" - --requirepass - "${REDIS_PASSWORD:-redis_dev_pwd}" healthcheck: test: ["CMD-SHELL", "redis-cli -a ${REDIS_PASSWORD:-redis_dev_pwd} ping | grep PONG"] interval: 5s timeout: 3s retries: 12 start_period: 5s # ── nginx:学生端 H5 站点 + /api 反代 ────────────── # 2026-10 起 H5 **不再由后端托管**(原来是 spring.web.resources.static-locations), # 改由本服务对外提供,后端退回纯 API。两者仍然**同源**,理由见 nginx/xt.conf 头部。 nginx: image: nginx:1.27-alpine container_name: xt-nginx restart: unless-stopped ports: - "${H5_PORT:-80}:80" volumes: # H5 构建产物(**产物不入库**):先在 frontend-mp 里跑 `pnpm build:h5`。 # ⚠️ 目录不存在时 docker 会**建一个空目录**,于是页面 404 而容器一切正常 # (`docker compose ps` 是 healthy、nginx 日志里也没有错)—— 先 build 再起。 - ${H5_DIR:-../frontend-mp/dist/build/h5}:/usr/share/nginx/html:ro - ./nginx/xt.conf:/etc/nginx/conf.d/default.conf:ro extra_hosts: # 后端是**宿主机上的 jar**,不在这个 compose 里。 # Docker Desktop 自带 host.docker.internal;Linux 上必须有下面这行才有这个名字 - "host.docker.internal:host-gateway" healthcheck: # 探的是"首页拿不拿得到",而不是"进程在不在" —— # 挂进来的产物目录是空的时候,前者才有意义。 # ⚠️ 必须写 **127.0.0.1**,不能写 localhost:容器里 localhost 会先解析到 IPv6 # ::1,而 nginx 的 `listen 80` 只监听 IPv4 → wget 报 Connection refused、 # 健康检查永远停在 unhealthy/starting(首页从宿主机看却是好的,极易误判)。 test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1/ || exit 1"] interval: 10s timeout: 3s retries: 6 start_period: 5s volumes: pg-data: redis-data: