Files
geMoldInsight/docker-compose.yml
T
cjw aaf887507f 🐛 fix(deploy): backend 宿主机端口受 .env BACKEND_PORT 控制
上一版 backend 写死 expose: ["8000"](不暴露宿主),但这违背"全局服
务的最终映射到宿主机只能受 .env 中的端口配置决定"的原则——调试场景下
.env 没办法把 backend 暴露到宿主。

修正:backend ports 改为 "${BACKEND_PORT:-}:8000",由 .env 决定:
- BACKEND_PORT 留空/未设 = 不暴露宿主端口(仅经前端 /api 反代)
- BACKEND_PORT=10003 = 暴露宿主 10003(调试 / 压测用)

.env.example 同步加注释说明。

验证:模拟 .env 两种场景下,端口映射完全由 BACKEND_PORT 决定。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-26 20:58:10 +08:00

138 lines
5.8 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.
# geMoldInsight — unified 模式(默认入口)
#
# 一键启动:
# docker compose up -d
#
# 其他模式(换文件名即可,无需 --profile):
# docker compose -f docker-compose.moldinsight.yml up -d
# docker compose -f docker-compose.inventory.yml up -d
#
# 注意:服务均未声明 profiles(compose 规则:声明了 profiles 的服务在
# 不带 --profile 时不会被选中,裸 up 会报 "no service selected"),
# 旧 --profile 写法不再是模式开关,模式切换唯一入口是 -f 文件名。
#
# 服务清单:frontend + backend(unified 入口) + moldinsight-celery
# 镜像:gemold-backend / gemold-frontend(celery 复用 gemold-backend,仅 command 不同)
# ---------------------------------------------------------------
# 公共环境变量(moldinsight 家族 backend/celery/moldinsight 共用)
# 通过 anchor 在本文件内复用,避免 environment 块重复
# ---------------------------------------------------------------
x-base-env: &base_env
DB_HOST: ${DB_HOST}
DB_PORT: ${DB_PORT:-5432}
DB_NAME: ${DB_NAME:-moldinsight}
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
REDIS_HOST: ${REDIS_HOST}
REDIS_PORT: ${REDIS_PORT:-6379}
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
RUSTFS_ENDPOINT: ${RUSTFS_ENDPOINT}
RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY}
RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY}
RUSTFS_TIMEOUT: ${RUSTFS_TIMEOUT:-30}
# SECRET_KEY 必须在 .env 中显式配置,否则 compose 直接失败
SECRET_KEY: ${SECRET_KEY:?SECRET_KEY 未配置:请在 .env 中设置}
ALGORITHM: ${ALGORITHM:-HS256}
ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-1440}
DEBUG: ${DEBUG:-false}
SERVE_FRONTEND_STATIC: ${SERVE_FRONTEND_STATIC:-false}
UPLOAD_DIR: ${UPLOAD_DIR:-./uploads}
MAX_FILE_SIZE: ${MAX_FILE_SIZE:-104857600}
ALLOWED_EXTENSIONS: ${ALLOWED_EXTENSIONS:-.stp,.step,.stp.gz}
POINTCLOUD_SAMPLE_COUNT: ${POINTCLOUD_SAMPLE_COUNT:-10000}
MESH_QUALITY: ${MESH_QUALITY:-high}
PARALLEL_PROCESSING: ${PARALLEL_PROCESSING:-true}
RUSTFS_PRESIGNED_URL_EXPIRES: ${RUSTFS_PRESIGNED_URL_EXPIRES:-3600}
ENABLE_FREECAD_VERIFICATION: ${ENABLE_FREECAD_VERIFICATION:-false}
FREECAD_VERIFICATION_TIMEOUT: ${FREECAD_VERIFICATION_TIMEOUT:-120}
LLM_ENABLED: ${LLM_ENABLED:-false}
LLM_API_URL: ${LLM_API_URL:-https://api.openai.com/v1}
LLM_API_KEY: ${LLM_API_KEY:-}
LLM_MODEL: ${LLM_MODEL:-gpt-4o-mini}
LLM_TIMEOUT: ${LLM_TIMEOUT:-60}
LLM_MAX_TOKENS: ${LLM_MAX_TOKENS:-2000}
services:
frontend:
build:
context: .
dockerfile: deploy/Dockerfile.frontend
image: gemold-frontend:latest
container_name: gemold_frontend
ports:
# 浏览器入口端口(默认 10003);容器内 nginx 监听 8000 反代到 backend 8000
- "${FRONTEND_PORT:-10003}:8000"
depends_on:
- backend
restart: unless-stopped
networks:
- gemold_network
backend:
build:
context: .
dockerfile: deploy/Dockerfile.moldinsight
image: gemold-backend:latest
container_name: gemold_backend
command: ["python", "-m", "uvicorn", "entrypoints.unified:app", "--host", "0.0.0.0", "--port", "8000"]
# 宿主机端口由 .env 的 BACKEND_PORT 决定:空/不设则不暴露宿主机端口
# (仅经前端 /api 反代同域访问,避免与 frontend 抢占宿主 10003)。
# 调试时设 BACKEND_PORT=10003 即可独立访问。
ports:
- "${BACKEND_PORT:-}:8000"
environment:
<<: *base_env
ADMIN_USERNAME: ${ADMIN_USERNAME:-admin}
ADMIN_PASSWORD: ${ADMIN_PASSWORD:?ADMIN_PASSWORD 未配置:请在 .env 中设置}
ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@gemold.com}
ADMIN_FULL_NAME: ${ADMIN_FULL_NAME:-系统管理员}
AUTO_MIGRATE: ${AUTO_MIGRATE:-true}
# 共享卷过渡兜底(D6/D11):主链路已改走 RustFS。uploads 供 RustFS 异常时
# 本地路径回退;html_output 仅作 /html 报告代理的存量兜底读(新产物不落本地)
volumes:
- uploads_data:/app/uploads
- html_data:/app/html_output
restart: unless-stopped
networks:
- gemold_network
moldinsight-celery:
# 与 backend 共用同一镜像(同一 build 声明 + 同一 tag,compose 只构建一次),
# 仅以 command 覆盖启动 worker——消除旧 Dockerfile.celery(已删)FROM
# gemold-backend 在并行构建下的"镜像尚不存在"陷阱,干净机器裸 up 一把过
build:
context: .
dockerfile: deploy/Dockerfile.moldinsight
image: gemold-backend:latest
container_name: gemold_celery
# cd /app/src 是必须的:celery_app / celery_tasks 是 src/ 的子模块,
# 而其 import 用的是裸模块名(celery_app.py 内 include=["celery_tasks"]),
# 所以 worker 必须从 src/ 目录启动;不依赖 celery 版本是否支持 --workdir
command: ["sh", "-c", "cd /app/src && exec celery -A celery_app worker --concurrency=${CELERY_CONCURRENCY:-2} --max-tasks-per-child=${CELERY_MAX_TASKS_PER_CHILD:-50} --loglevel=info"]
environment:
<<: *base_env
# Celery/OCC 吞吐调优(OCC_THROUGHPUT 方案 A)
CELERY_CONCURRENCY: ${CELERY_CONCURRENCY:-2}
CELERY_MAX_TASKS_PER_CHILD: ${CELERY_MAX_TASKS_PER_CHILD:-50}
# uploads_data 共享卷(D6 过渡兜底):RustFS 异常时 worker 回退本地路径下载。
# D11 后 worker 不再写 HTML 产物(直传 RustFS 报告键),无需 html_data 卷
volumes:
- uploads_data:/app/uploads
depends_on:
- backend
restart: unless-stopped
networks:
- gemold_network
networks:
gemold_network:
# 固定 name,便于跨 compose 文件调试时容器互通(如 inventory-only 与 unified 临时联调)
name: gemold_network
driver: bridge
volumes:
uploads_data:
name: gemold_uploads_data
html_data:
name: gemold_html_data