决策:E2E 活栈在 runner 内用 docker compose 起全栈(postgres + redis + minio + backend), 与本地验证路径完全一致;未采纳「service containers + runner 上 mvn package 后 java -jar」—— 那需要为后端另写一套 host 网络配置,等于制造第二条与本地不一致的路径。 本机实测(与 CI 同一序列):中间件三项 healthcheck 全 Healthy(pg_isready / redis-cli ping / mc ready local)→ backend /api/v1/health/live 返回 200 → seed 幂等可执行(INSERT 0 0) → pytest tests/e2e → 49 passed。 (本机限制:Docker Hub 不可达且无 temurin 基础镜像,未复现 --build;改用本地既有镜像为底座、 挂载当日 16:24 构建的 jar,使被验证的代码版本与 CI 一致 —— 否则是拿 09-09 的旧代码验 09-18 的用例。) 修掉的 6 处缺陷: 1. minio/minio:latest 是滚动 tag → pin RELEASE.2025-09-07T16-13-09Z(否则 CI 拉到的镜像 与本地验证时不同,表现为不可复现的偶发失败) 2. up 未显式列出 minio(靠 depends_on 隐式拉起),而 minio 的 healthcheck 正是 backend 能否启动的前置条件 3. up --build 把构建与起栈耦合,失败日志混杂 → 拆为 build / up 两步 4. 就绪窗口 5min 偏紧(首次构建后仍需 Spring 启动 + Flyway 46 个迁移)→ 7.5min 5. 缺 down -v 前置清卷:seed 用 ON CONFLICT (username) DO NOTHING,残留卷会让账号口令 停留在上一轮 → 登录 401,并伪装成业务失败 6. job 无 timeout(GH Actions 默认 360 分钟)→ timeout-minutes: 30 另:pytest -v → pytest tests/e2e -v。原以为从仓库根收集会误收 tests/*_test.py (其在 import 期依赖 psycopg2 与 E2E_DB_PASSWORD),实测否定:pytest.ini 的 testpaths = tests/e2e 已限定范围,从根收集正是 49 个用例且无 error。显式传参作为兜底保留。 计划 Task 2.3 由「依赖基础设施决策」改为「已决策并落地」,仅余 Step 3(CI 上实测一次绿)。
124 lines
3.8 KiB
YAML
124 lines
3.8 KiB
YAML
# 丹阳公益婚恋服务平台 - 本地完整环境
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
container_name: danyang-match-postgres
|
|
environment:
|
|
POSTGRES_DB: danyang_match
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: ${DB_PASSWORD:?请在本地 .env 设置 DB_PASSWORD}
|
|
ports:
|
|
- "5434:5432"
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U postgres -d danyang_match"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
container_name: danyang-match-redis
|
|
ports:
|
|
- "6381:6379"
|
|
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:?请在本地 .env 设置 REDIS_PASSWORD}
|
|
volumes:
|
|
- redis_data:/data
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:?请在本地 .env 设置 REDIS_PASSWORD}", "ping"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
minio:
|
|
# pin 到确定版本:`latest` 是滚动 tag,MinIO 已多次改动镜像内容(如移除内嵌 console),
|
|
# 用 `latest` 会让 CI 的 E2E 拉到一个与本地验证时不同的镜像 → 不可复现的偶发失败。
|
|
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
|
|
container_name: danyang-match-minio
|
|
command: server /data --console-address ":9001"
|
|
environment:
|
|
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:?请在本地 .env 设置 MINIO_ACCESS_KEY}
|
|
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:?请在本地 .env 设置 MINIO_SECRET_KEY}
|
|
ports:
|
|
- "9003:9000"
|
|
- "9004:9001"
|
|
volumes:
|
|
- minio_data:/data
|
|
healthcheck:
|
|
test: ["CMD", "mc", "ready", "local"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
backend:
|
|
build:
|
|
context: ../backend
|
|
dockerfile: Dockerfile
|
|
container_name: danyang-match-backend
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
minio:
|
|
condition: service_healthy
|
|
environment:
|
|
SPRING_PROFILES_ACTIVE: docker
|
|
DB_HOST: postgres
|
|
DB_PORT: 5432
|
|
DB_NAME: danyang_match
|
|
DB_USER: postgres
|
|
DB_PASSWORD: ${DB_PASSWORD:?请在本地 .env 设置 DB_PASSWORD}
|
|
REDIS_HOST: redis
|
|
REDIS_PORT: 6379
|
|
REDIS_PASSWORD: ${REDIS_PASSWORD:?请在本地 .env 设置 REDIS_PASSWORD}
|
|
MINIO_ENDPOINT: http://minio:9000
|
|
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:?请在本地 .env 设置 MINIO_ACCESS_KEY}
|
|
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:?请在本地 .env 设置 MINIO_SECRET_KEY}
|
|
JWT_ACCESS_SECRET: ${JWT_ACCESS_SECRET:?请在本地 .env 设置 JWT_ACCESS_SECRET}
|
|
JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:?请在本地 .env 设置 JWT_REFRESH_SECRET}
|
|
ENCRYPTION_KEY: ${ENCRYPTION_KEY:?请在本地 .env 设置 ENCRYPTION_KEY}
|
|
WECHAT_APP_ID: dev-wechat-app-id
|
|
WECHAT_APP_SECRET: ${WECHAT_APP_SECRET:-}
|
|
ports:
|
|
- "8085:8080"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget -qO /dev/null http://localhost:8080/api/v1/health/live || exit 1"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
|
|
admin-web:
|
|
build:
|
|
context: ../admin-web
|
|
dockerfile: Dockerfile
|
|
container_name: danyang-match-admin
|
|
depends_on:
|
|
backend:
|
|
condition: service_healthy
|
|
|
|
nginx:
|
|
image: nginx:alpine
|
|
container_name: danyang-match-nginx
|
|
depends_on:
|
|
backend:
|
|
condition: service_healthy
|
|
admin-web:
|
|
condition: service_started
|
|
ports:
|
|
- "6688:80"
|
|
volumes:
|
|
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget -qO /dev/null http://localhost/nginx-health || exit 1"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
|
|
volumes:
|
|
postgres_data:
|
|
redis_data:
|
|
minio_data:
|