File size: 2,311 Bytes
579a226
f26e640
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
579a226
 
 
 
f26e640
 
 
579a226
 
 
 
 
 
f26e640
 
 
a920dd4
 
579a226
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5ad73b1
 
579a226
5ad73b1
 
579a226
a920dd4
 
 
579a226
 
 
 
 
a920dd4
f26e640
 
 
 
 
 
 
a920dd4
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
services:
  # ---------- Self-hosted Turnstile/CF solver (no third-party API) ----------
  turnstile-solver:
    build: ./solver
    container_name: turnstile-solver
    restart: unless-stopped
    environment:
      PORT: 9988
      MAX_WORKERS: ${SOLVER_WORKERS:-8}
      CAMOUFOX_HEADLESS: virtual
    # Solver does not need to be exposed to the host — playwright-api reaches
    # it over the internal Docker network. Uncomment the ports stanza below
    # if you want to test it directly.
    # ports:
    #   - "9988:9988"
    shm_size: "1gb"
    healthcheck:
      test: ["CMD-SHELL", "curl -fsS http://localhost:9988/health > /dev/null || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 60s
    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "5"
    networks:
      - internal

  # ---------- Playwright execution API ----------
  playwright-api:
    build: .
    container_name: playwright-api
    restart: unless-stopped
    depends_on:
      turnstile-solver:
        condition: service_healthy

    ports:
      - "${HOST_PORT:-7860}:7860"

    environment:
      PORT: 7860
      TIMEOUT_MS: ${TIMEOUT_MS:-1800000}
      # Wired to the bundled solver — no external URL, no API key.
      TURNSTILE_SOLVER_URL: http://turnstile-solver:9988
      WHISPER_MODEL: ${WHISPER_MODEL:-Xenova/whisper-tiny.en}
      COOKIES_DIR: /app/cookies

    shm_size: "2gb"
    ipc: host

    deploy:
      resources:
        limits:
          cpus: "${CPU_LIMIT:-4.0}"
          memory: "${MEM_LIMIT:-8g}"

    healthcheck:
      test: ["CMD-SHELL", "curl -fsS http://localhost:7860/health > /dev/null || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 30s

    # tmpfs mounts default to root:root,755 which the UID-1000 container user
    # can't write to. Pin uid/gid to 1000 and 0700 so /app/runs is writable.
    tmpfs:
      - /tmp:size=2g,exec,uid=1000,gid=1000,mode=1777
      - /app/runs:size=512m,exec,uid=1000,gid=1000,mode=0700

    volumes:
      - playwright-cookies:/app/cookies

    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "5"

    networks:
      - internal

networks:
  internal:
    driver: bridge

volumes:
  playwright-cookies: