diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..507cce2 --- /dev/null +++ b/.env.example @@ -0,0 +1,30 @@ +# asset_helper —— 编排环境变量示例 +# +# 使用:cp .env.example .env,按需填写后由 docker compose 自动加载 +# 同一份 .env 同时被 docker-compose.yml 和 docker-compose.dev.yml 读取, +# 测试环境对必填项有默认兜底值,正式环境强制要求 JWT_SECRET / POSTGRES_PASSWORD。 + +# ===== 必填(正式环境)===== +JWT_SECRET=please-change-me-to-a-long-random-string +POSTGRES_PASSWORD=please-change-me + +# ===== 可选 ===== +POSTGRES_USER=postgres +RUST_LOG=info + +# ===== 端口(默认值见 docker-compose.yml / docker-compose.dev.yml)===== +# 正式环境 +# GATEWAY_HTTP_PORT=80 +# GATEWAY_HTTPS_PORT=443 +# ADMIN_WEB_PORT=20080 + +# 测试环境 +# GATEWAY_HTTP_PORT=18080 +# GATEWAY_HTTPS_PORT=18443 +# ADMIN_WEB_PORT=18888 +# USER_POSTGRES_PORT=20101 +# USER_REDIS_PORT=20103 +# USER_LOGIN_ACCOUNT_PORT=20111 +# USER_REGISTER_ACCOUNT_PORT=20112 +# USER_LOGIN_EMAIL_PORT=20113 +# USER_REGISTER_EMAIL_PORT=20114 diff --git a/CLAUDE.md b/CLAUDE.md index 0415dc6..ece9a87 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -66,8 +66,28 @@ HTTP 非 200 时网关统一返回 `{ "error", "message", "code" }`。 - 改移动端:`cd app && claude` - 跨端联调或修改公共契约:在项目根目录启动,本文件提供总览 +## 部署 + +项目使用根目录的两份 docker compose 文件做整体编排,**不再使用各子目录下的独立 compose**: + +| 文件 | 用途 | 启动命令 | +|------|------|---------| +| [docker-compose.yml](docker-compose.yml) | 正式环境 | `docker compose up -d --build` | +| [docker-compose.dev.yml](docker-compose.dev.yml) | 测试/开发环境 | `docker compose -f docker-compose.dev.yml up -d --build` | + +**首次部署:** +1. `cp .env.example .env` +2. 填入 `JWT_SECRET`、`POSTGRES_PASSWORD`(正式环境必需) +3. 执行上方启动命令 + +**核心差异:** +- 正式:仅暴露网关 80/443、前端 20080;数据卷 `user-postgres-data` / `user-redis-data` +- 测试:全部端口暴露便于调试;网关 18080/18443、前端 18888;数据卷加 `-dev` 后缀,与正式完全隔离 +- 两套环境可同机并存 + ## 项目当前进展 - ✅ `backend/` — 用户服务(账号/邮箱 登录/注册)已搭起雏形,Nginx 网关 + Postgres + Redis 编排就绪 +- ✅ 全栈一键编排(根目录 docker-compose.yml / docker-compose.dev.yml) - ⬜ `frontend/` — 未启动 - ⬜ `app/` — 未启动 diff --git a/backend/CLAUDE.md b/backend/CLAUDE.md index c188197..1581b02 100644 --- a/backend/CLAUDE.md +++ b/backend/CLAUDE.md @@ -29,7 +29,6 @@ backend/ │ ├── user-login-email/ # 邮箱登录服务 (port 8003) │ ├── user-register-email/ # 邮箱注册服务 (port 8004) │ ├── migrations/ # 数据库初始化 SQL -│ ├── docker-compose.yml # 用户服务本地编排 │ └── Dockerfile # 通用/遗留构建文件 ├── gateway/ # API 网关 │ ├── Dockerfile @@ -46,6 +45,8 @@ backend/ └── README.md ``` +> 编排已统一上移到项目根目录的 `docker-compose.yml` / `docker-compose.dev.yml`,本目录不再存放 compose 文件。 + ## 微服务架构说明 ### 服务拆分原则 @@ -192,7 +193,7 @@ OK ### 5. Docker 构建 -- 各微服务 Dockerfile 的构建上下文为**项目根目录**(`docker-compose.yml` 中使用 `context: ../..`)。 +- 各微服务 Dockerfile 的构建上下文为 **`backend/` 目录**(根目录 `docker-compose.yml` 中使用 `context: ./backend`)。 - 构建采用多阶段(builder + runtime),基于 `rust:1.94.1-alpine3.23` 编译,最终运行在 `alpine:3.23`。 - 共享代码更新时,需确保 `shared/` 目录在 Dockerfile 中被正确复制。 @@ -206,10 +207,21 @@ OK ## 常用命令 -### 启动用户服务(本地开发) +### 启动整套后端(含网关 + 数据库 + 缓存) + +后端不再单独编排,由项目根目录的 docker compose 一并启动。详见 [根目录 CLAUDE.md](../CLAUDE.md#部署)。 + ```bash -cd services/user-service -docker-compose up --build +# 在项目根目录 +docker compose -f docker-compose.dev.yml up -d --build # 测试 +docker compose up -d --build # 正式 +``` + +如需仅启动后端栈(不含前端)做联调: + +```bash +docker compose -f docker-compose.dev.yml up -d --build user-db user-redis \ + user-login-account user-register-account user-login-email user-register-email gateway ``` ### 网关管理 diff --git a/backend/gateway/docker-compose.yml b/backend/gateway/docker-compose.yml deleted file mode 100644 index 48b04fc..0000000 --- a/backend/gateway/docker-compose.yml +++ /dev/null @@ -1,29 +0,0 @@ -version: "3.8" - -services: - gateway: - build: - context: . - dockerfile: Dockerfile - container_name: api-gateway - ports: - - "80:80" - - "443:443" - volumes: - # 开发环境:挂载配置便于热更新,生产环境应内嵌在镜像中 - - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - - ./nginx/conf.d:/etc/nginx/conf.d:ro - networks: - - default - - frontend_asset-helper-network - restart: unless-stopped - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost/health"] - interval: 30s - timeout: 3s - start_period: 5s - retries: 3 - -networks: - frontend_asset-helper-network: - external: true diff --git a/backend/gateway/nginx/nginx.conf b/backend/gateway/nginx/nginx.conf index 9fa8436..09adaed 100644 --- a/backend/gateway/nginx/nginx.conf +++ b/backend/gateway/nginx/nginx.conf @@ -44,29 +44,28 @@ http { # 连接限制 limit_conn_zone $binary_remote_addr zone=addr:10m; - # 上游服务 —— 通过宿主机端口访问各微服务(开发环境) - # 生产环境应改为容器名:端口,并确保同网络 + # 上游服务 —— 通过 Docker 内部 DNS(服务名)访问,统一由根目录 docker-compose 编排 upstream user_login_account { least_conn; - server host.docker.internal:20111 max_fails=3 fail_timeout=30s; + server user-login-account:8080 max_fails=3 fail_timeout=30s; keepalive 32; } upstream user_register_account { least_conn; - server host.docker.internal:20112 max_fails=3 fail_timeout=30s; + server user-register-account:8080 max_fails=3 fail_timeout=30s; keepalive 32; } upstream user_login_email { least_conn; - server host.docker.internal:20113 max_fails=3 fail_timeout=30s; + server user-login-email:8080 max_fails=3 fail_timeout=30s; keepalive 32; } upstream user_register_email { least_conn; - server host.docker.internal:20114 max_fails=3 fail_timeout=30s; + server user-register-email:8080 max_fails=3 fail_timeout=30s; keepalive 32; } diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..6517b4b --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,191 @@ +# asset_helper —— 测试环境一键编排 +# +# 使用: +# docker compose -f docker-compose.dev.yml up -d --build +# +# 与正式环境的差异: +# 1. 项目名 / 容器名 / 网络 / 数据卷 全部带 -dev 后缀,与正式完全隔离 +# 2. 微服务、Postgres、Redis 端口全部暴露宿主机,便于调试 +# 3. 网关、前端使用不同对外端口,可与正式环境同机并存 +# 4. 敏感值(JWT_SECRET、POSTGRES_PASSWORD)提供默认值,方便快速启动 + +name: asset-helper-dev + +services: + # ============ 数据层 ============ + user-db: + image: postgres:18.3-alpine3.23 + container_name: user-db-dev + environment: + - POSTGRES_USER=${POSTGRES_USER:-postgres} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-postgres} + - POSTGRES_DB=user-db + volumes: + - user-postgres-data-dev:/var/lib/postgresql/data + - ./backend/services/user-service/migrations:/docker-entrypoint-initdb.d:ro + ports: + - "${USER_POSTGRES_PORT:-20101}:5432" + networks: + - asset-helper-dev + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d user-db"] + interval: 10s + timeout: 5s + retries: 5 + + user-redis: + image: redis:8.6.2-alpine + container_name: user-redis-dev + volumes: + - user-redis-data-dev:/data + ports: + - "${USER_REDIS_PORT:-20103}:6379" + networks: + - asset-helper-dev + restart: unless-stopped + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + # ============ 用户微服务 ============ + user-login-account: + build: + context: ./backend + dockerfile: services/user-service/user-login-account/Dockerfile + container_name: user-login-account-dev + environment: + - RUST_LOG=${RUST_LOG:-debug} + - DATABASE_URL=postgres://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@user-db:5432/user-db + - REDIS_URL=redis://user-redis:6379/0 + - SERVICE_NAME=user-login-account + - SERVICE_PORT=8080 + - JWT_SECRET=${JWT_SECRET:-dev-secret-key} + ports: + - "${USER_LOGIN_ACCOUNT_PORT:-20111}:8080" + depends_on: + user-db: + condition: service_healthy + user-redis: + condition: service_healthy + networks: + - asset-helper-dev + restart: unless-stopped + + user-register-account: + build: + context: ./backend + dockerfile: services/user-service/user-register-account/Dockerfile + container_name: user-register-account-dev + environment: + - RUST_LOG=${RUST_LOG:-debug} + - DATABASE_URL=postgres://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@user-db:5432/user-db + - REDIS_URL=redis://user-redis:6379/0 + - SERVICE_NAME=user-register-account + - SERVICE_PORT=8080 + ports: + - "${USER_REGISTER_ACCOUNT_PORT:-20112}:8080" + depends_on: + user-db: + condition: service_healthy + user-redis: + condition: service_healthy + networks: + - asset-helper-dev + restart: unless-stopped + + user-login-email: + build: + context: ./backend + dockerfile: services/user-service/user-login-email/Dockerfile + container_name: user-login-email-dev + environment: + - RUST_LOG=${RUST_LOG:-debug} + - DATABASE_URL=postgres://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@user-db:5432/user-db + - REDIS_URL=redis://user-redis:6379/0 + - SERVICE_NAME=user-login-email + - SERVICE_PORT=8080 + - JWT_SECRET=${JWT_SECRET:-dev-secret-key} + ports: + - "${USER_LOGIN_EMAIL_PORT:-20113}:8080" + depends_on: + user-db: + condition: service_healthy + user-redis: + condition: service_healthy + networks: + - asset-helper-dev + restart: unless-stopped + + user-register-email: + build: + context: ./backend + dockerfile: services/user-service/user-register-email/Dockerfile + container_name: user-register-email-dev + environment: + - RUST_LOG=${RUST_LOG:-debug} + - DATABASE_URL=postgres://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@user-db:5432/user-db + - REDIS_URL=redis://user-redis:6379/0 + - SERVICE_NAME=user-register-email + - SERVICE_PORT=8080 + ports: + - "${USER_REGISTER_EMAIL_PORT:-20114}:8080" + depends_on: + user-db: + condition: service_healthy + user-redis: + condition: service_healthy + networks: + - asset-helper-dev + restart: unless-stopped + + # ============ API 网关 ============ + gateway: + build: + context: ./backend/gateway + dockerfile: Dockerfile + container_name: api-gateway-dev + ports: + - "${GATEWAY_HTTP_PORT:-18080}:80" + - "${GATEWAY_HTTPS_PORT:-18443}:443" + depends_on: + - user-login-account + - user-register-account + - user-login-email + - user-register-email + networks: + - asset-helper-dev + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost/health"] + interval: 30s + timeout: 3s + start_period: 5s + retries: 3 + + # ============ 前端管理后台 ============ + admin-web: + build: + context: ./frontend + dockerfile: docker/Dockerfile + container_name: asset-helper-admin-dev + ports: + - "${ADMIN_WEB_PORT:-18888}:80" + depends_on: + - gateway + networks: + - asset-helper-dev + restart: unless-stopped + +networks: + asset-helper-dev: + name: asset-helper-dev + driver: bridge + +volumes: + user-postgres-data-dev: + name: user-postgres-data-dev + user-redis-data-dev: + name: user-redis-data-dev diff --git a/backend/services/user-service/docker-compose.yml b/docker-compose.yml similarity index 50% rename from backend/services/user-service/docker-compose.yml rename to docker-compose.yml index 15e1b89..bda3985 100644 --- a/backend/services/user-service/docker-compose.yml +++ b/docker-compose.yml @@ -1,133 +1,33 @@ -version: "3.8" +# asset_helper —— 正式环境一键编排 +# +# 使用: +# 1. 复制 .env.example 为 .env,填入 JWT_SECRET 等敏感值 +# 2. docker compose up -d --build +# +# 暴露端口(默认): +# - 80/443 网关(对外) +# - 20080 前端管理后台(对外) +# 微服务、Postgres、Redis 仅在内部网络可达,不暴露宿主机端口。 + +name: asset-helper services: - user-login-account: - build: - context: ../.. - dockerfile: services/user-service/user-login-account/Dockerfile - container_name: user-login-account - environment: - - RUST_LOG=info - - DATABASE_URL=postgres://postgres:postgres@user-db:5432/user-db - - REDIS_URL=redis://user-redis:6379/0 - - SERVICE_NAME=user-login-account - - SERVICE_PORT=8080 - - JWT_SECRET=${JWT_SECRET:-dev-secret-key} - ports: - - "${USER_LOGIN_ACCOUNT_PORT:-20111}:8080" - depends_on: - user-db: - condition: service_healthy - user-redis: - condition: service_healthy - networks: - - user-network - restart: unless-stopped - healthcheck: - test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"] - interval: 30s - timeout: 10s - retries: 3 - - user-register-account: - build: - context: ../.. - dockerfile: services/user-service/user-register-account/Dockerfile - container_name: user-register-account - environment: - - RUST_LOG=info - - DATABASE_URL=postgres://postgres:postgres@user-db:5432/user-db - - REDIS_URL=redis://user-redis:6379/0 - - SERVICE_NAME=user-register-account - - SERVICE_PORT=8080 - ports: - - "${USER_REGISTER_ACCOUNT_PORT:-20112}:8080" - depends_on: - user-db: - condition: service_healthy - user-redis: - condition: service_healthy - networks: - - user-network - restart: unless-stopped - healthcheck: - test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"] - interval: 30s - timeout: 10s - retries: 3 - - user-login-email: - build: - context: ../.. - dockerfile: services/user-service/user-login-email/Dockerfile - container_name: user-login-email - environment: - - RUST_LOG=info - - DATABASE_URL=postgres://postgres:postgres@user-db:5432/user-db - - REDIS_URL=redis://user-redis:6379/0 - - SERVICE_NAME=user-login-email - - SERVICE_PORT=8080 - - JWT_SECRET=${JWT_SECRET:-dev-secret-key} - ports: - - "${USER_LOGIN_EMAIL_PORT:-20113}:8080" - depends_on: - user-db: - condition: service_healthy - user-redis: - condition: service_healthy - networks: - - user-network - restart: unless-stopped - healthcheck: - test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"] - interval: 30s - timeout: 10s - retries: 3 - - user-register-email: - build: - context: ../.. - dockerfile: services/user-service/user-register-email/Dockerfile - container_name: user-register-email - environment: - - RUST_LOG=info - - DATABASE_URL=postgres://postgres:postgres@user-db:5432/user-db - - REDIS_URL=redis://user-redis:6379/0 - - SERVICE_NAME=user-register-email - - SERVICE_PORT=8080 - ports: - - "${USER_REGISTER_EMAIL_PORT:-20114}:8080" - depends_on: - user-db: - condition: service_healthy - user-redis: - condition: service_healthy - networks: - - user-network - restart: unless-stopped - healthcheck: - test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"] - interval: 30s - timeout: 10s - retries: 3 - + # ============ 数据层 ============ user-db: image: postgres:18.3-alpine3.23 container_name: user-db environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres + - POSTGRES_USER=${POSTGRES_USER:-postgres} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?need POSTGRES_PASSWORD in .env} - POSTGRES_DB=user-db volumes: - user-postgres-data:/var/lib/postgresql/data - - ./migrations:/docker-entrypoint-initdb.d:ro - ports: - - "${USER_POSTGRES_PORT:-20101}:5432" + - ./backend/services/user-service/migrations:/docker-entrypoint-initdb.d:ro networks: - - user-network + - asset-helper restart: unless-stopped healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres -d user-db"] + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d user-db"] interval: 10s timeout: 5s retries: 5 @@ -137,10 +37,8 @@ services: container_name: user-redis volumes: - user-redis-data:/data - ports: - - "${USER_REDIS_PORT:-20103}:6379" networks: - - user-network + - asset-helper restart: unless-stopped healthcheck: test: ["CMD", "redis-cli", "ping"] @@ -148,8 +46,130 @@ services: timeout: 5s retries: 5 + # ============ 用户微服务 ============ + user-login-account: + build: + context: ./backend + dockerfile: services/user-service/user-login-account/Dockerfile + container_name: user-login-account + environment: + - RUST_LOG=${RUST_LOG:-info} + - DATABASE_URL=postgres://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@user-db:5432/user-db + - REDIS_URL=redis://user-redis:6379/0 + - SERVICE_NAME=user-login-account + - SERVICE_PORT=8080 + - JWT_SECRET=${JWT_SECRET:?need JWT_SECRET in .env} + depends_on: + user-db: + condition: service_healthy + user-redis: + condition: service_healthy + networks: + - asset-helper + restart: unless-stopped + + user-register-account: + build: + context: ./backend + dockerfile: services/user-service/user-register-account/Dockerfile + container_name: user-register-account + environment: + - RUST_LOG=${RUST_LOG:-info} + - DATABASE_URL=postgres://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@user-db:5432/user-db + - REDIS_URL=redis://user-redis:6379/0 + - SERVICE_NAME=user-register-account + - SERVICE_PORT=8080 + depends_on: + user-db: + condition: service_healthy + user-redis: + condition: service_healthy + networks: + - asset-helper + restart: unless-stopped + + user-login-email: + build: + context: ./backend + dockerfile: services/user-service/user-login-email/Dockerfile + container_name: user-login-email + environment: + - RUST_LOG=${RUST_LOG:-info} + - DATABASE_URL=postgres://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@user-db:5432/user-db + - REDIS_URL=redis://user-redis:6379/0 + - SERVICE_NAME=user-login-email + - SERVICE_PORT=8080 + - JWT_SECRET=${JWT_SECRET} + depends_on: + user-db: + condition: service_healthy + user-redis: + condition: service_healthy + networks: + - asset-helper + restart: unless-stopped + + user-register-email: + build: + context: ./backend + dockerfile: services/user-service/user-register-email/Dockerfile + container_name: user-register-email + environment: + - RUST_LOG=${RUST_LOG:-info} + - DATABASE_URL=postgres://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@user-db:5432/user-db + - REDIS_URL=redis://user-redis:6379/0 + - SERVICE_NAME=user-register-email + - SERVICE_PORT=8080 + depends_on: + user-db: + condition: service_healthy + user-redis: + condition: service_healthy + networks: + - asset-helper + restart: unless-stopped + + # ============ API 网关 ============ + gateway: + build: + context: ./backend/gateway + dockerfile: Dockerfile + container_name: api-gateway + ports: + - "${GATEWAY_HTTP_PORT:-80}:80" + - "${GATEWAY_HTTPS_PORT:-443}:443" + depends_on: + - user-login-account + - user-register-account + - user-login-email + - user-register-email + networks: + - asset-helper + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost/health"] + interval: 30s + timeout: 3s + start_period: 5s + retries: 3 + + # ============ 前端管理后台 ============ + admin-web: + build: + context: ./frontend + dockerfile: docker/Dockerfile + container_name: asset-helper-admin + ports: + - "${ADMIN_WEB_PORT:-20080}:80" + depends_on: + - gateway + networks: + - asset-helper + restart: unless-stopped + networks: - user-network: + asset-helper: + name: asset-helper driver: bridge volumes: diff --git a/frontend/CLAUDE.md b/frontend/CLAUDE.md index ab409e5..52dc00a 100644 --- a/frontend/CLAUDE.md +++ b/frontend/CLAUDE.md @@ -23,34 +23,16 @@ - 与 `app/`(移动/桌面端)共享后端,但 UI 实现独立 - 当前为后台管理系统,后续可扩展为面向用户的 Web 端 -## Docker 开发与部署 +## Docker 部署 -### 开发环境(热更新,不污染物理机) +前端**不再单独编排**,统一由项目根目录的 docker compose 一并启动。详见 [根目录 CLAUDE.md](../CLAUDE.md#部署)。 -```bash -cd frontend -docker-compose -f docker-compose.dev.yml up --build -``` +| 环境 | 启动命令(在项目根目录执行) | 访问地址 | +|------|------|---------| +| 正式 | `docker compose up -d --build` | `http://localhost:20080` | +| 测试 | `docker compose -f docker-compose.dev.yml up -d --build` | `http://localhost:18888` | -- 访问:`http://localhost:3000` -- 源码通过 volume 挂载,修改后自动热更新 -- API 请求通过 Vite proxy 转发到后端网关(默认走 Docker 网络容器名 `http://api-gateway`,需保证网关加入 `frontend_asset-helper-network`) - -**如需修改后端地址:** -```bash -VITE_API_BASE_URL=http://your-backend:80 docker-compose -f docker-compose.dev.yml up -``` - -### 生产构建与部署 - -```bash -cd frontend -docker-compose up --build -``` - -- 访问:`http://localhost:20080`(端口可通过 `ADMIN_WEB_PORT` 环境变量修改) -- 多阶段构建:Node 构建 → Nginx 提供静态文件 -- Nginx 代理 `/api/*` 到后端网关容器 +两套环境前端均为多阶段构建(Node 构建 → Nginx 静态托管),通过 Nginx 的 `location /api/` 反代到网关容器(服务名 `gateway`,同 Docker 网络内可达)。 ## 与后端的协作约定 @@ -110,9 +92,8 @@ interface ErrorResponse { ``` frontend/ ├── docker/ -│ ├── Dockerfile # 生产多阶段构建 -│ ├── Dockerfile.dev # 开发环境(volume 挂载源码) -│ └── nginx.conf # 生产 Nginx SPA 配置 +│ ├── Dockerfile # 多阶段构建(Node 构建 + Nginx 静态托管) +│ └── nginx.conf # 生产 Nginx SPA 配置 + /api 反代到网关 ├── src/ │ ├── api/ │ │ ├── client.ts # Axios 封装(device/language 注入、JWT、错误处理) @@ -136,14 +117,14 @@ frontend/ │ │ └── storage.ts # localStorage 封装(带前缀隔离) │ ├── App.tsx # 根组件(ConfigProvider + RouterProvider) │ └── main.tsx # 入口 -├── docker-compose.dev.yml # 开发编排(热更新) -├── docker-compose.yml # 生产编排 ├── index.html ├── package.json ├── tsconfig.json / tsconfig.app.json / tsconfig.node.json └── vite.config.ts ``` +> 编排文件已统一上移到项目根目录的 `docker-compose.yml` / `docker-compose.dev.yml`。 + ## API 调用规范 **必须使用封装函数,禁止直接 fetch/axios:** @@ -176,9 +157,8 @@ const result = await loginAccount({ account: 'xxx', password: 'xxx' }) ## 开发环境 -- 后端网关默认通过 Docker 网络或 `host.docker.internal` 访问 -- 开发容器内 Vite 监听 `0.0.0.0:5173`,映射到宿主机 `3000` -- 如需后端使用 HTTPS 自签名证书,Vite proxy 已配置 `secure: false` +- 推荐:在项目根目录用 `docker compose -f docker-compose.dev.yml up -d --build` 启动整套测试环境,前端为 Nginx 静态托管,访问 `http://localhost:18888` +- 如需快速调试前端而不构建镜像,本目录下 `npm run dev` 可启动 Vite dev server(监听 `0.0.0.0:5173`),需自行确保后端网关在宿主机可达;可通过 `VITE_API_BASE_URL` 覆盖 proxy 目标 ## 扩展指南 diff --git a/frontend/docker-compose.dev.yml b/frontend/docker-compose.dev.yml deleted file mode 100644 index fa8bfe8..0000000 --- a/frontend/docker-compose.dev.yml +++ /dev/null @@ -1,30 +0,0 @@ -services: - admin-web-dev: - build: - context: . - dockerfile: docker/Dockerfile.dev - container_name: asset-helper-admin-dev - environment: - - NODE_ENV=development - - CHOKIDAR_USEPOLLING=true - # 走 Docker 网络容器名,规避 host.docker.internal 仅解析到 IPv6 导致的连接失败 - - VITE_API_BASE_URL=${VITE_API_BASE_URL:-http://api-gateway} - ports: - - "3000:5173" - volumes: - # 源码挂载(实现热更新) - - ./src:/app/src:ro - - ./index.html:/app/index.html:ro - - ./vite.config.ts:/app/vite.config.ts:ro - - ./tsconfig.json:/app/tsconfig.json:ro - - ./tsconfig.app.json:/app/tsconfig.app.json:ro - - ./tsconfig.node.json:/app/tsconfig.node.json:ro - # 不覆盖 node_modules - - /app/node_modules - networks: - - asset-helper-network - restart: unless-stopped - -networks: - asset-helper-network: - driver: bridge diff --git a/frontend/docker-compose.yml b/frontend/docker-compose.yml deleted file mode 100644 index 2f71399..0000000 --- a/frontend/docker-compose.yml +++ /dev/null @@ -1,22 +0,0 @@ -version: "3.8" - -services: - admin-web: - build: - context: . - dockerfile: docker/Dockerfile - container_name: asset-helper-admin - ports: - - "${ADMIN_WEB_PORT:-20080}:80" - networks: - - asset-helper-network - restart: unless-stopped - healthcheck: - test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80/"] - interval: 30s - timeout: 10s - retries: 3 - -networks: - asset-helper-network: - driver: bridge diff --git a/frontend/docker/Dockerfile.dev b/frontend/docker/Dockerfile.dev deleted file mode 100644 index d6e1ad4..0000000 --- a/frontend/docker/Dockerfile.dev +++ /dev/null @@ -1,16 +0,0 @@ -# 开发环境 Dockerfile -# 不复制源码,通过 docker-compose volume 挂载,实现热更新 - -FROM node:20-alpine - -WORKDIR /app - -# 安装依赖(利用 Docker 缓存层) -COPY package.json package-lock.json* ./ -RUN npm install - -# 暴露 Vite 开发服务器端口 -EXPOSE 5173 - -# 开发模式启动(--host 确保外部可访问) -CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]