name: siteforge-v5 services: siteforge: build: context: . dockerfile: Dockerfile image: siteforge/web:5.0 init: true restart: unless-stopped ports: - "127.0.0.1:${SITEFORGE_PORT:-8787}:8787" environment: SITEFORGE_DATA_DIR: /data SITEFORGE_ADMIN_PASSWORD: ${SITEFORGE_ADMIN_PASSWORD:?Set SITEFORGE_ADMIN_PASSWORD in .env} SITEFORGE_SESSION_SECRET: ${SITEFORGE_SESSION_SECRET:?Set SITEFORGE_SESSION_SECRET in .env} SITEFORGE_COOKIE_SECURE: "${SITEFORGE_COOKIE_SECURE:-false}" SITEFORGE_ALLOWED_HOSTS: "${SITEFORGE_ALLOWED_HOSTS:-localhost,127.0.0.1,testserver}" SITEFORGE_PUBLISH_ROOT: /published SITEFORGE_REQUIRE_RELEASE_APPROVAL: "true" volumes: - siteforge_data:/data - siteforge_published:/published read_only: true tmpfs: - /tmp:size=128m,mode=1777 security_opt: - no-new-privileges:true cap_drop: - ALL pids_limit: 128 healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8787/api/health', timeout=3)"] interval: 30s timeout: 5s retries: 3 start_period: 30s worker: build: context: . dockerfile: Dockerfile image: siteforge/web:5.0 init: true restart: unless-stopped command: ["python", "-m", "app.worker"] environment: SITEFORGE_DATA_DIR: /data SITEFORGE_JOB_POLL_SECONDS: "1.5" SITEFORGE_JOB_MAX_ATTEMPTS: "3" volumes: - siteforge_data:/data read_only: true tmpfs: - /tmp:size=128m,mode=1777 security_opt: - no-new-privileges:true cap_drop: - ALL pids_limit: 128 volumes: siteforge_data: siteforge_published: