version: '3.8' services: web: build: context: . dockerfile: frontend/Dockerfile restart: unless-stopped # Architecture §2.2: this is the only service exposed to the host. The # default.conf file is mounted as a template; scripts/nginx-entrypoint.sh # parses ${RUSTFS_ENDPOINT} and writes the rendered config to # /etc/nginx/conf.d/default.conf before exec'ing nginx. ports: - "${GATEWAY_PORT:-8888}:80" volumes: - ./default.conf:/etc/nginx/conf.d/default.conf.template:ro - ./scripts/nginx-entrypoint.sh:/docker-entrypoint.sh:ro environment: RUSTFS_ENDPOINT: ${RUSTFS_ENDPOINT:-http://rustfs:9000} depends_on: - backend - runtime backend: build: context: . dockerfile: backend/Dockerfile restart: unless-stopped # No host port: architecture §2.2 — only Nginx is externally reachable. # No local-FS volume: backend stores everything in RustFS (RUSTFS_*). environment: DATABASE_URL: mysql+asyncmy://${MYSQL_USER:-model_platform}:${MYSQL_PASSWORD:-model_platform}@mysql:3306/${MYSQL_DATABASE:-model_platform}?charset=utf8mb4 JWT_SECRET: ${JWT_SECRET:-local-jwt-secret} INITIAL_ADMIN_PASSWORD: ${INITIAL_ADMIN_PASSWORD:-admin12345} RUNTIME_API_URL: http://runtime:8000 RUSTFS_ENDPOINT: ${RUSTFS_ENDPOINT:-http://rustfs:9000} RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY:-modelplatform} RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY:-modelplatformsecret} RUSTFS_TRASH_BUCKET: ${RUSTFS_TRASH_BUCKET:-trash} RUSTFS_TRASH_RETENTION_DAYS: ${RUSTFS_TRASH_RETENTION_DAYS:-30} volumes: - ./backend:/app/backend:ro - ./common:/app/common:ro depends_on: - runtime runtime: build: context: . dockerfile: runtime/Dockerfile restart: unless-stopped cap_add: - SYS_ADMIN devices: - /dev/fuse:/dev/fuse security_opt: - apparmor:unconfined # No host port: architecture §2.2 — only Nginx is externally reachable. environment: DATABASE_URL: mysql+asyncmy://${MYSQL_USER:-model_platform}:${MYSQL_PASSWORD:-model_platform}@mysql:3306/${MYSQL_DATABASE:-model_platform}?charset=utf8mb4 SERVICE_NAME: runtime-manager WORKSPACES_ROOT: /workspace/workspaces PUBLIC_BASE_URL: http://runtime REMOTE_BUCKET: rustfs:workspaces RCLONE_CONFIG_RUSTFS_TYPE: s3 RCLONE_CONFIG_RUSTFS_PROVIDER: Other RCLONE_CONFIG_RUSTFS_ACCESS_KEY_ID: ${RUSTFS_ACCESS_KEY:-modelplatform} RCLONE_CONFIG_RUSTFS_SECRET_ACCESS_KEY: ${RUSTFS_SECRET_KEY:-modelplatformsecret} RCLONE_CONFIG_RUSTFS_ENDPOINT: ${RUSTFS_ENDPOINT:-http://rustfs:9000} RCLONE_CONFIG_RUSTFS_ENV_AUTH: "false" RCLONE_CONFIG_RUSTFS_FORCE_PATH_STYLE: "true" RCLONE_CONFIG_RUSTFS_REGION: other volumes: - ./deploy/data/workspaces:/workspace/workspaces - ./runtime:/app/runtime:ro - ./common:/app/common:ro schedule: build: context: . dockerfile: schedule/Dockerfile restart: unless-stopped # No host port: architecture §2.2 — only Nginx is externally reachable. # No local-FS volume: schedule executes nodes via tempfile.TemporaryDirectory # under Python's default temp dir (cleaned per-run); artifacts live in RustFS. environment: DATABASE_URL: mysql+asyncmy://${MYSQL_USER:-model_platform}:${MYSQL_PASSWORD:-model_platform}@mysql:3306/${MYSQL_DATABASE:-model_platform}?charset=utf8mb4 RUSTFS_ENDPOINT: ${RUSTFS_ENDPOINT:-http://rustfs:9000} RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY:-modelplatform} RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY:-modelplatformsecret} depends_on: - backend