The playwright WS-server path (camoufox.server.launch_server) is incompatible
with playwright >=1.45: camoufox 0.4.11's launchServer.js requires
playwright/driver/package/lib/browserServerImpl.js, which no longer exists in
any playwright 1.45-1.60 → tradein-browser crash-looped with MODULE_NOT_FOUND
('Server process terminated unexpectedly'). Verified by running the built image.
Pivot (no playwright protocol between containers):
- browser/server.py: aiohttp service holding a local AsyncCamoufox (headless,
os/locale/geoip/humanize, proxy from SCRAPER_PROXY_URL). POST /fetch {url} →
new_page/goto/content/close → {html}; GET /health. Page-recycle every N +
crash-recovery (relaunch + 1 retry), serialized via asyncio.Lock.
- browser/Dockerfile: +aiohttp (camoufox fetch-as-root/#908 block untouched).
- backend BrowserFetcher: playwright.connect → httpx POST to the browser service
(one retry on transport/HTTP error). All playwright imports dropped.
- config: browser_ws_endpoint → browser_http_endpoint (http://tradein-browser:3000).
Verified by a REAL local image build + run: image builds, container stays Up
(Restarts=0, no crash-loop), GET /health=200, POST /fetch launches camoufox and
drives Firefox (only NS_ERROR_UNKNOWN_HOST = no DNS egress in the local build env,
proving the full HTTP→camoufox→Firefox chain; real fetch validates on prod with
network+proxy). 7 unit tests + ruff clean.
Dormant: scraper_fetch_mode stays curl_cffi. Refs #905, #883, #884
44 lines
1.8 KiB
Docker
44 lines
1.8 KiB
Docker
# tradein-browser — camoufox Playwright WS server (изолированный контейнер Firefox).
|
||
# Backend подключается к этому контейнеру через playwright.firefox.connect.
|
||
|
||
FROM python:3.12-slim
|
||
|
||
ENV PYTHONUNBUFFERED=1 \
|
||
PYTHONDONTWRITEBYTECODE=1
|
||
|
||
# Firefox runtime libs + ca-certificates для TLS
|
||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||
apt-get update && apt-get install -y --no-install-recommends \
|
||
libgtk-3-0 \
|
||
libasound2 \
|
||
libdbus-glib-1-2 \
|
||
libx11-xcb1 \
|
||
libxtst6 \
|
||
ca-certificates \
|
||
&& useradd --create-home --uid 1000 app
|
||
|
||
WORKDIR /app
|
||
|
||
# camoufox[geoip] тянет playwright как зависимость
|
||
RUN pip install --no-cache-dir "camoufox[geoip]" aiohttp
|
||
|
||
COPY server.py ./server.py
|
||
|
||
# camoufox fetch качает (а) Firefox-сборку и (б) GeoLite2 mmdb (geoip=True).
|
||
# Firefox идёт в $HOME/.cache → ENV HOME=/home/app кладёт его в кэш app-юзера,
|
||
# куда рантайм его ищет (фикс #899). НО mmdb пишется в site-packages пакета
|
||
# camoufox (root-owned после pip install) — под app это PermissionError на
|
||
# GeoLite2-City.mmdb. Поэтому fetch выполняем под ROOT (пишет и mmdb, и —
|
||
# благодаря ENV HOME — Firefox в /home/app/.cache), затем chown'им Firefox-кэш
|
||
# на app. mmdb остаётся root-owned в site-packages (world-readable → app читает
|
||
# на рантайме). Verified реальной сборкой образа 2026-05-31.
|
||
ENV HOME=/home/app
|
||
|
||
RUN python -m camoufox fetch && chown -R app:app /home/app/.cache
|
||
|
||
USER app
|
||
|
||
EXPOSE 3000
|
||
|
||
CMD ["python", "server.py"]
|