refactor(storage): 对象存储从 MinIO 换成 SeaweedFS(钉 4.47)
动机:MinIO 的 GitHub 仓库已于 2026-02 归档,不再产出安全补丁,已累积多个 CVE 且不修;本项目存身份证 / 实名材料 / 用户照片,无人修 CVE 才是真正驱动因素 (Docker Hub 下架只是表象,quay.io 仍在提供)。 变更: - 三套 compose(dev / staging / prod)的 minio 服务替换为 seaweedfs 4.47: 覆盖 entrypoint 渲染 -s3.config 注入 identity(S3 网关默认不鉴权,必须显式开启), -volume.max=100 解除第二个 bucket 写入时的 InternalError。 - 新增一次性 storage-init 容器,经 filer 接口预建 public / private 桶 (SeaweedFS PutObject 到不存在的 bucket 直接失败;全仓库原无任何 createBucket)。 - S3Config 显式开启 path-style:AWS SDK v1 默认 virtual-host 会把 bucket 拼进 主机名,容器名在 DNS 中不存在必然失败(本机有 http_proxy 时易误判为 502 拒绝)。 - ci.yml:镜像校验与起栈步骤改为 seaweedfs + storage-init。 - 运维脚本 health-check.sh / run-uat.sh 的 MinIO 探针改为 SeaweedFS (S3 网关开启鉴权后匿名根请求返回 403,200/403 均算存活)。 注:path-style 与建桶属换存储的必要项;presigned URL 的 host 须对外可达这一 既有缺陷(原 minio:9000 直发客户端不可达)留待下一轮「改缺陷」处理。
This commit is contained in:
@@ -39,23 +39,67 @@ services:
|
||||
- danyang-net
|
||||
restart: unless-stopped
|
||||
|
||||
minio:
|
||||
# 同 docker-compose.yml 的 minio 条目:Docker Hub 上 minio/minio 仓库已被整体移除
|
||||
# (MinIO 自 2025-10 起停止发布容器镜像,仅源码分发),生产环境同样拉不到。
|
||||
# 改为仍在提供镜像的 quay.io —— 这是真实的部署阻塞,不只是 CI 问题。
|
||||
# 版本与本地/CI 保持一致,钉死为 CI 实测确认可用的 RELEASE.2025-09-07T16-13-09Z。
|
||||
image: quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z
|
||||
container_name: danyang-match-minio
|
||||
command: server /data --console-address ":9001"
|
||||
seaweedfs:
|
||||
# 同 docker-compose.yml:对象存储已从 MinIO 换成 SeaweedFS。
|
||||
# 生产换的动力比 CI 更强 —— MinIO 仓库已归档、不再产出安全补丁,
|
||||
# 而这里存的是身份证与实名材料。详见 docker-compose.yml 中的完整说明。
|
||||
# 版本与本地/CI 一致(钉 4.47),避免各环境跑不同实现。
|
||||
image: chrislusf/seaweedfs:4.47
|
||||
container_name: danyang-match-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_ROOT_USER: ${MINIO_ACCESS_KEY:?请设置MINIO_ACCESS_KEY}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:?请设置MINIO_SECRET_KEY}
|
||||
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:?请设置MINIO_ACCESS_KEY}
|
||||
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:?请设置MINIO_SECRET_KEY}
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
- seaweedfs_data:/data
|
||||
networks:
|
||||
- danyang-net
|
||||
healthcheck:
|
||||
# 与本地一致:鉴权开启后匿名列桶返回 403,故 200/403 都算健康。
|
||||
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
|
||||
restart: unless-stopped
|
||||
|
||||
storage-init:
|
||||
# SeaweedFS 不会自动建桶,PutObject 到不存在的 bucket 直接失败。
|
||||
# 生产同样必须预建 public / private,否则照片与实名材料全部上传不了。
|
||||
# 走 filer 目录接口,无需签名,复用同一镜像的 curl。幂等:201 新建 / 409 已存在。
|
||||
image: chrislusf/seaweedfs:4.47
|
||||
container_name: danyang-match-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
|
||||
networks:
|
||||
- danyang-net
|
||||
restart: "no"
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ../backend
|
||||
@@ -66,6 +110,10 @@ services:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
seaweedfs:
|
||||
condition: service_healthy
|
||||
storage-init:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
SPRING_PROFILES_ACTIVE: docker,production
|
||||
SPRING_CONFIG_IMPORT: configtree:/run/secrets/
|
||||
@@ -76,7 +124,8 @@ services:
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: 6379
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:?请设置REDIS_PASSWORD}
|
||||
MINIO_ENDPOINT: http://minio:9000
|
||||
# 变量名仍为 MINIO_*(服务端配置键未改),实际指向 SeaweedFS 的 S3 网关。
|
||||
MINIO_ENDPOINT: http://seaweedfs:8333
|
||||
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:?请设置MINIO_ACCESS_KEY}
|
||||
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:?请设置MINIO_SECRET_KEY}
|
||||
JWT_ACCESS_SECRET: ${JWT_ACCESS_SECRET:?请设置JWT_ACCESS_SECRET}
|
||||
@@ -138,7 +187,7 @@ services:
|
||||
volumes:
|
||||
postgres_data:
|
||||
redis_data:
|
||||
minio_data:
|
||||
seaweedfs_data:
|
||||
|
||||
networks:
|
||||
danyang-net:
|
||||
|
||||
Reference in New Issue
Block a user