Files
geMoldInsight/docker-compose.moldinsight.yml
cjw f87cd8a68e fix(deploy): celery worker --pool=solo——prefork 守护进程禁止 spawn OCC 子进程
Celery prefork 的 worker 子进程是 daemonic,multiprocessing 硬性禁止
守护进程再生子进程:OccProcessPool(spawn 拉起 OCC 常驻工作进程)在
celery worker 内首次 run 即报 "daemonic processes are not allowed to
have children",解析任务全部 failed。该池在 FastAPI 主进程内无此限制
——celery 路径的分析从未真正工作过。

改用 --pool=solo:任务在 celery 主进程(非守护)内执行,允许 spawn;
天然单任务串行,与 processing_service / redis_task_manager / db_manager
等模块级单例的 asyncio.Lock(不可跨循环并发)匹配。吞吐扩展走横向
加容器副本。CELERY_CONCURRENCY / MAX_TASKS_PER_CHILD 随之移除。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-27 00:01:05 +08:00

115 lines
4.7 KiB
YAML
Raw Permalink 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 — moldinsight-only 模式
#
# 一键启动:
# docker compose -f docker-compose.moldinsight.yml up -d
#
# 服务清单:moldinsight(独立 API)+ moldinsight-celery(异步分析 worker)
# 不含前端、不含 inventory。
# 镜像:两服务共用 gemold-backend:latest(同一 build 声明,compose 只构建一次;
# celery 仅以 command 覆盖启动 worker),无跨镜像构建依赖,干净机器裸 up 一把过。
# 注意:服务未声明 profiles(避免裸 up 报 "no service selected"),
# 模式切换唯一入口是 -f 文件名。
# ---------------------------------------------------------------
# 公共环境变量(moldinsight 家族共用)
# ---------------------------------------------------------------
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: ${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:
moldinsight:
build:
context: .
dockerfile: deploy/Dockerfile.moldinsight
# 统一用 gemold-backend tag(历史 gemold-moldinsight:latest 双 tag 已废弃)
image: gemold-backend:latest
container_name: gemold_moldinsight
command: ["python", "-m", "uvicorn", "entrypoints.moldinsight:app", "--host", "0.0.0.0", "--port", "8000"]
ports:
- "${MOLDINSIGHT_PORT}:8000"
environment:
<<: *base_env
HOST: 0.0.0.0
PORT: "8000"
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}
# uploads_data:D6 过渡兜底,RustFS 异常时本地路径回退
# html_data:D11 后仅作 /html 报告代理的存量兜底读(新产物不落本地)
volumes:
- uploads_data:/app/uploads
- html_data:/app/html_output
restart: unless-stopped
networks:
- gemold_network
moldinsight-celery:
# 与 moldinsight 共用同一镜像,仅 command 覆盖启动 worker
build:
context: .
dockerfile: deploy/Dockerfile.moldinsight
image: gemold-backend:latest
container_name: gemold_celery
# --pool=solo:任务在 celery 主进程内执行。prefork 的 worker 子进程是
# daemonic,multiprocessing 禁止守护进程再生子进程,OCC 常驻进程池
# (OccProcessPool spawn 拉起)在 prefork 下必报
# "daemonic processes are not allowed to have children"(2026-09-26)。
# solo 天然单任务串行,与模块级单例(asyncio.Lock 不可跨循环并发)匹配;
# 需要吞吐时横向加容器副本,而不是调并发。
command: ["sh", "-c", "cd /app/src && exec celery -A celery_app worker --pool=solo --loglevel=info"]
environment:
<<: *base_env
# 旧 CELERY_CONCURRENCY / CELERY_MAX_TASKS_PER_CHILD 已随 --pool=solo 移除:
# solo 单进程串行,二者不适用(.env 里残留定义会被 compose 静默忽略)
volumes:
- uploads_data:/app/uploads
# 注:本文件无 backend service,celery 必须等 moldinsight API 就绪后再启动
depends_on:
- moldinsight
restart: unless-stopped
networks:
- gemold_network
networks:
gemold_network:
name: gemold_network
driver: bridge
volumes:
uploads_data:
name: gemold_uploads_data
html_data:
name: gemold_html_data