Files
danyang-match/infrastructure/docker-compose.staging.yml
T
WorkBuddy dc0a62d4c5 fix(storage): presigned URL 改用对外可达 host,修复客户端直传断链
SeaweedFS 换存储后 MINIO_ENDPOINT 变为 seaweedfs:8333(容器名),
PhotoService 生成的 presigned URL 把该 host 直接下发给客户端,
客户端不在 docker 网络内无法解析 → 直传/直链全断。

- S3Config:新增 amazonS3Signer Bean,指向 object-storage.public-endpoint
  (缺省回退内网 endpoint,向后兼容)。独立签名端是因为 SigV4 签名覆盖
  host 头,事后改 URL 字符串会让签名失效返 403;独立客户端让签名 host
  与客户端实际命中的 host 天然一致。
- PhotoService:去掉 @RequiredArgsConstructor,改显式 @Qualifier 构造器;
  getUploadToken / getSignedUrl / getSignedUrlForAuthorizedReview 三处
  presigned 生成改用 amazonS3Signer;putObject 服务端上传仍走内网 amazonS3。
- application-docker.yml / application-dev.yml:public-endpoint 读
  MINIO_PUBLIC_ENDPOINT(缺省回退 MINIO_ENDPOINT)。
- 三套 compose:注入 MINIO_PUBLIC_ENDPOINT
  (dev localhost:8333 / staging localhost:8334 / prod 留作单一旋钮)。
- 测试:PhotoServiceTest 新增嵌套 PresignedUrlPublicHostTest,用真实
  AmazonS3 客户端(仅本地签名不联网)断言下发 URL host 为对外地址、
  不含 seaweedfs 容器名;同步补齐两处 5→6 参构造调用。

验证:本机 65 E2E 全绿 + storage_link_probe path-style 全通 +
PhotoServiceTest/PhotoUploadValidationTest/PhotoLimitGuardTest 19 例单测全绿。

顺带:backend/maven-settings.xml 的 Central 兜底由投毒的 repo1.maven.org
改为可达的 repo.maven.apache.org,使本机镜像构建可走 aliyun 主源。
2026-09-22 17:10:40 +08:00

150 lines
5.6 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Staging Docker Compose(预发环境,仅开发/测试)
version: '3.8'
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: danyang_match_staging
POSTGRES_USER: staging
POSTGRES_PASSWORD: staging_dev_password_change_me
ports:
- "5433:5432"
volumes:
- postgres_staging_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U staging -d danyang_match_staging"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6380:6379"
command: redis-server --appendonly yes --requirepass staging-redis-pass-change-me
volumes:
- redis_staging_data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "staging-redis-pass-change-me", "ping"]
interval: 10s
timeout: 5s
retries: 5
seaweedfs:
# 同 docker-compose.yml:对象存储已从 MinIO 换成 SeaweedFS(钉 4.47)。
# staging 与本地/生产保持同一实现,避免「只有预发用的是另一套存储」这类偏差。
image: chrislusf/seaweedfs:4.47
container_name: danyang-match-staging-seaweedfs
# 必须覆盖 entrypoint:镜像 ENTRYPOINT 是 /usr/bin/weed,只写 command 会被追加成
# `weed sh -c ...` → `weed: unknown subcommand "sh"`(本地实测踩到)。
entrypoint: ["sh", "-c"]
command:
- |
cat > /tmp/s3cfg.json <<CFG
{"identities":[{"name":"app","credentials":[{"accessKey":"$${MINIO_ACCESS_KEY}","secretKey":"$${MINIO_SECRET_KEY}"}],"actions":["Admin","Read","Write","List","Tagging"]}]}
CFG
# -volume.max=100:bucket 名即 collection,默认上限 8 个 volume 只够一个 bucket
# (第二个桶写入会 InternalError)。详见 docker-compose.yml 中的说明。
exec weed server -s3 -s3.port=8333 -s3.config=/tmp/s3cfg.json -dir=/data -volume.max=100
environment:
MINIO_ACCESS_KEY: staging
MINIO_SECRET_KEY: staging_dev_password
ports:
# 与生产错开一位(8080/8081、5432/5433 同理):本地栈的 8333 已被占,故用 8334。
- "8334:8333"
- "9334:9333"
- "8889:8888"
volumes:
- seaweedfs_staging_data:/data
healthcheck:
test: ["CMD-SHELL", "code=$$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8333/); [ \"$$code\" = 200 ] || [ \"$$code\" = 403 ]"]
interval: 5s
timeout: 5s
retries: 24
storage-init:
# 同 docker-compose.yml:SeaweedFS 不自动建桶,必须预建 public / private。
image: chrislusf/seaweedfs:4.47
container_name: danyang-match-staging-storage-init
depends_on:
seaweedfs:
condition: service_healthy
entrypoint:
- sh
- -c
- |
for b in public private; do
code=$$(curl -s -o /dev/null -w '%{http_code}' "http://seaweedfs:8888/buckets/$$b/" || echo 000)
if [ "$$code" = "200" ]; then echo "bucket $$b: already exists"; continue; fi
i=0
while [ $$i -lt 30 ]; do
code=$$(curl -s -o /dev/null -w '%{http_code}' -X POST "http://seaweedfs:8888/buckets/$$b/" || echo 000)
case "$$code" in 200|201|409) break ;; esac
i=$$((i+1)); sleep 2
done
echo "bucket $$b: create -> $$code"
done
restart: "no"
backend:
build:
context: ../backend
dockerfile: Dockerfile
container_name: danyang-match-staging-backend
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
SPRING_PROFILES_ACTIVE: staging
DB_HOST: postgres
DB_PORT: 5432
DB_NAME: danyang_match_staging
DB_USER: staging
DB_PASSWORD: staging_dev_password_change_me
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: staging-redis-pass-change-me
MINIO_ENDPOINT: http://seaweedfs:8333
# 客户端直传 presigned URL 用:staging S3 网关 publish 到宿主 8334。
MINIO_PUBLIC_ENDPOINT: http://localhost:8334
MINIO_ACCESS_KEY: staging
MINIO_SECRET_KEY: staging_dev_password
JWT_ACCESS_SECRET: staging-access-secret-dev-only
JWT_REFRESH_SECRET: staging-refresh-secret-dev-only
CHECKIN_TOKEN_SECRET: staging-checkin-secret-dev-only
ENCRYPTION_KEY: 32539f3d2fa8123dcec899cc3dbee7347034123a126ac22fcb4702e10c454d50
FEATURES_APPEAL_ENABLED: "true"
ports:
- "8081:8080"
healthcheck:
# 探针用 127.0.0.1 而非 localhost:busybox wget 解析 localhost 时可能优先取 ::1,
# 而服务若只绑 IPv4 会导致探针假失败(本地栈的 nginx 已实测踩到)。
test: ["CMD-SHELL", "curl -f http://127.0.0.1:8080/api/v1/health/ready || exit 1"]
interval: 30s
timeout: 10s
retries: 3
admin-web:
build:
context: ../admin-web
dockerfile: Dockerfile
container_name: danyang-match-staging-admin
depends_on:
- backend
ports:
# staging 与生产同机共存,全部端口按「生产 + 1」错开(5433/6380/8081/13521)。
# 生产管理端为 13520(admin-web/vite.config.ts + docker-compose.prod.yml),
# 故此处为 13521 —— 与 tests/uat/run-uat.sh 的 UAT_ADMIN_URL 默认值一致,
# 两处均由 ui-tests/ui-document-baseline-contracts.mjs 钉住。
# 管理端构建产物部署在 /admin/ 子路径下(见 admin-web/vite.config.ts 的 base),
# 故直连访问地址为 http://localhost:13521/admin/ 。
- "13521:80"
volumes:
postgres_staging_data:
redis_staging_data:
seaweedfs_staging_data: