services: locg-api: build: . container_name: locg-api restart: unless-stopped environment: - PORT=8070 # FlareSolverr solves Cloudflare's challenge for LOCG (datacenter IPs get # 403'd otherwise). Reached by service name on the homelab docker network. - FLARESOLVERR_URL=http://flaresolverr:8191 # Optional: route FlareSolverr's egress through a clean/residential proxy # when LOCG serves this IP a 200 "Restricted" page. Set in the host env. - FLARESOLVERR_PROXY=${FLARESOLVERR_PROXY:-} # Detail-page enrichment: cache each comic's scraped detail for this many # hours (releases don't change after shipping) and limit concurrent detail # fetches to stay gentle on FlareSolverr's single browser. - DETAIL_TTL_HOURS=168 - DETAIL_CONCURRENCY=2 depends_on: - flaresolverr healthcheck: test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:8070/health"] interval: 30s timeout: 5s retries: 3 start_period: 10s deploy: resources: limits: cpus: '0.5' memory: 256M networks: - homelab flaresolverr: image: ghcr.io/flaresolverr/flaresolverr:latest container_name: flaresolverr restart: unless-stopped # Chrome crashes (and FlareSolverr answers HTTP 500) with Docker's default # 64MB /dev/shm. Give the browser real shared memory. shm_size: "1gb" # Chrome's built-in async DNS resolver fails against Docker's embedded DNS # (127.0.0.11), which surfaces as "net::ERR_NAME_NOT_RESOLVED" on every # solve. Pin real resolvers. This container only ever dials public hosts, # so losing embedded DNS (and thus service-name lookups) costs nothing. dns: - 1.1.1.1 - 8.8.8.8 environment: - LOG_LEVEL=info - TZ=UTC healthcheck: test: ["CMD", "curl", "-s", "-o", "/dev/null", "http://localhost:8191/"] interval: 30s timeout: 5s retries: 3 start_period: 20s deploy: resources: limits: cpus: '1.5' memory: 1024M networks: - homelab networks: homelab: external: true