name: mangacircus x-app: &app image: ${APP_IMAGE:-mangacircus:local} build: context: . args: VCS_REF: ${VCS_REF:-development} init: true restart: unless-stopped stop_grace_period: 90s read_only: true tmpfs: [/tmp] security_opt: [no-new-privileges:true] cap_drop: [ALL] secrets: [scraper_token] logging: driver: local options: max-size: "10m" max-file: "3" services: reader: <<: *app image: ${READER_IMAGE:-${APP_IMAGE:-mangacircus:local}} command: [node, runtime/launch.js, reader] ports: ["${READER_BIND:-127.0.0.1}:${READER_PORT:-8080}:8080"] volumes: - type: bind source: ${LIBRARY_PATH:-./library} target: /library read_only: true bind: {create_host_path: false} - type: bind source: ${DATA_PATH:-./data} target: /data bind: {create_host_path: false} # Built-in backups (docs/backup.md). The folder must exist and be writable by # uid 1000; backups stay off unless BACKUP_PATH is set. - type: bind source: ${BACKUP_PATH:-./backup} target: /backup bind: {create_host_path: false} environment: PORT: "8080" DATA: /data LIBRARY: /library BACKUP: ${BACKUP_PATH:+/backup} TZ: ${TZ:-UTC} SIGNUP: closed SCAN_INTERVAL: "10" SCAN_CONCURRENCY: ${SCAN_CONCURRENCY:-8} COOKIE_SECURE: ${COOKIE_SECURE:-0} READING_WINDOWS_JSON: ${READING_WINDOWS_JSON:-} READING_TIMEZONE: ${READING_TIMEZONE:-UTC} READING_QUIZ_UNLOCK_MINUTES: ${READING_QUIZ_UNLOCK_MINUTES:-60} READING_QUIZ_CATALOG_PATH: ${READING_QUIZ_CATALOG_PATH:-} SCRAPER_URL: http://scraper:8091 SCRAPER_TOKEN_FILE: /run/secrets/scraper_token DISCOVERY_HARVEST_AT: ${DISCOVERY_HARVEST_AT:-03:30} DISCOVERY_ANILIST_URL: ${DISCOVERY_ANILIST_URL:-} GREATEST_COVER_WARM: ${GREATEST_COVER_WARM:-1} READ_AHEAD: ${READ_AHEAD:-1} PERF_TRACE: ${PERF_TRACE:-0} networks: [backend, egress] healthcheck: test: [CMD, node, tools/healthcheck.js, reader] interval: 30s timeout: 5s start_period: 60s retries: 3 scraper: <<: *app command: [node, runtime/launch.js, scraper] volumes: - type: bind source: ${LIBRARY_PATH:-./library} target: /library bind: {create_host_path: false} - type: bind source: ${SCRAPER_DATA_PATH:-./data/scraper} target: /data/scraper bind: {create_host_path: false} - type: bind source: ${PEER_DATA_PATH:-./data/peering} target: /data/peering read_only: true environment: DATA: /data LIBRARY: /library SCRAPER_DATA: /data/scraper METADATA_CACHE: /data/scraper/metadata/anilist TZ: ${TZ:-UTC} SCRAPER_HOST: 0.0.0.0 SCRAPER_PORT: "8091" SCRAPER_TOKEN_FILE: /run/secrets/scraper_token PEER_DATA: /data/peering networks: [backend, egress] healthcheck: test: [CMD, node, tools/healthcheck.js, scraper] interval: 30s timeout: 5s start_period: 60s retries: 3 peer-gateway: <<: *app profiles: [peering] command: [node, peering/gateway.js] ports: ["${PEER_BIND:-127.0.0.1}:${PEER_PORT:-8093}:8093"] volumes: - type: bind source: ${LIBRARY_PATH:-./library} target: /library read_only: true bind: {create_host_path: false} - type: bind source: ${PEER_DATA_PATH:-./data/peering} target: /data/peering read_only: true - type: bind source: ${PEER_USAGE_PATH:-./data/peering-usage} target: /data/peering-usage environment: LIBRARY: /library PEER_DATA: /data/peering PEER_USAGE_FILE: /data/peering-usage/usage.json PEER_HOST: 0.0.0.0 PEER_PORT: "8093" # Docker (Desktop) does not publish host ports from an internal-only network. networks: [backend, egress] healthcheck: test: [CMD, node, tools/healthcheck-peer.js] interval: 30s timeout: 5s start_period: 30s retries: 3 networks: backend: internal: true egress: {} secrets: scraper_token: file: ${SCRAPER_TOKEN_PATH:-./.secrets/scraper_token}