This document outlines the containerized execution environment, production-only orchestration policies, and persistent storage structure for the WebAI-to-API runtime.
Status: Production Hardening
Scope: Containerization, Environment Orchestration, and Volume Persistence
For user-facing Docker setup instructions, see Docker Guide.
The Docker Deployment Model provides environment parity across development, testing, and production phases. By encapsulating dependencies, Playwright-native system packages, and web automation drivers inside a standard container runtime, the deployment layer enforces process isolation and provides a clean environment for browser operations.
- Container Configuration: Standardizes execution runtime, Python path structures, and logging pipelines.
- Orchestration Boundaries: Manages production-hardened process execution, port exposures, and automatic recovery boundaries.
- Persistence Policies: Standardizes volume mounts to ensure browser session profiles survive container lifecycles.
The containerized environment operates under defined technical constraints to ensure predictable and consistent automation.
- Base Image: Uses the Playwright-native standard image
mcr.microsoft.com/playwright/python:v1.62.0-noble. - Pre-configured Drivers: Contains system-level dependencies for running headless Chromium processes without needing runtime package downloads.
PYTHONUNBUFFERED=1: Forces stdout and stderr streams to be unbuffered. This guarantees real-time log ingestion by Docker/system daemons without buffering delays.PYTHONPATH=/app/src: Registers the server source code directory into Python'ssys.path, ensuring standard import resolution across all modules.PLAYWRIGHT_HEADLESS=true: Enforces headless operation for browser runtimes inside headless server environments.
The WebAI-to-API server is orchestrated strictly for production execution using Docker Compose.
The service is defined in docker-compose.yml for production execution:
- Detached Execution: The service is typically run using
docker compose up -dto prevent interruption from terminal closures. - Container Restart Policy: Enforces
restart: alwaysto automatically recover from process crashes or host reboots. - Port Exposure: Maps host port
6969to container port6969. - Environment Configuration: Loads variables from
.envand applies container runtime settings such asPYTHONPATHandPLAYWRIGHT_HEADLESS. - Persistent Runtime State: Mounts
./config.conf(read-only) and./runtimeinto the container to preserve application settings, browser authentication state, conversation snapshots, and runtime-generated cache directories. Application logs are emitted to stdout/stderr.
The current deployment model operates in a single-worker configuration:
- Single Process Topology: Uvicorn runs with
--workers 1. - No Dynamic Reloading: The container runs without source watching or
--reloadmode. - Static Container Image: Application source code is baked into the image at build time and is not bind-mounted into the running container.
Browser session data is persisted through mounted volumes, ensuring it survives container rollbacks, redeployments, and normal container restarts.
- Ephemeral assets: Source files, dependencies, and internal Playwright page caches are stored in transient container layers and discarded on container rebuilds.
- Persistent runtime files:
config.conf: Application settings (mounted read-only).runtime/auth/gemini.json: Cookies and session state.runtime/conversations/: SQLite conversation snapshots.runtime/cache/: Runtime-generated cache.- Logs: Application logs are streamed to stdout/stderr.
- Bind mount configuration:
- Maps the local host file
./config.confto/app/config.conf(read-only). - Maps the local host path
./runtimeto/app/runtime.
- Maps the local host file
- Volume persistence: Runtime-generated state files are written within the mounted volume, surviving container recreation.
The included Makefile provides operational targets for managing the container lifecycle:
| Command | Operation | Details |
|---|---|---|
make build |
docker build -t cornatul/webai.ai:latest . |
Builds the local Docker image using the default cache. |
make build-fresh |
docker build --no-cache -t cornatul/webai.ai:latest . |
Rebuilds the container from scratch, ignoring cached layers. |
make up |
docker compose up -d |
Launches the container in detached mode using the project's Docker Compose configuration. |
make up-attach |
docker compose up |
Launches the container in the foreground and streams logs to the terminal. |
make logs |
docker compose logs -f web_ai |
Follows logs from the running web_ai service. |
make stop |
docker compose down |
Stops and removes active container instances and associated networks. |
make down |
docker compose down |
Stops and removes container allocations (identical to make stop). |
To verify container state and session authorization:
The Playwright backend requires pre-generated authentication state for Docker deployments. The browser-based login flow requires a display environment and must be run on the HOST machine, not inside the Docker container.
Production Authentication Workflow:
-
On your HOST machine, run the bootstrap login utility:
poetry run python verify_login.py
-
Complete the Google sign-in process in the browser window that opens.
-
Verify the authentication state file was created:
ls runtime/auth/gemini.json
-
Start the Docker container (it will consume the auth state via volume mount):
make up
The ./runtime:/app/runtime volume mount ensures runtime/auth/gemini.json is available inside the container at /app/runtime/auth/gemini.json, where the Playwright context automatically loads the authentication cookies.
Note: The /v1/auth/login endpoint is NOT supported in Docker deployments because it requires a headful display environment.
WebAI-to-API supports two distinct authentication approaches:
Gemini WebAPI Backend:
- Uses unofficial API wrappers
- Authenticates via cookies (
__Secure-1PSID,__Secure-1PSIDTS) - Cookies configured in
config.conf[Gemini] section - No browser required
- Works immediately in Docker
Gemini Playwright Backend:
- Drives real Chromium browser via Playwright
- Requires
runtime/auth/gemini.jsonauthentication state file - State file generated by
verify_login.pyon HOST machine - Docker container consumes state file via volume mount
- Provides maximum resilience against web UI changes
Authentication State File (runtime/auth/gemini.json):
This file contains Playwright storageState data including:
- Google authentication cookies
- LocalStorage data
- Origin permissions
The file is created on the HOST machine by verify_login.py and consumed by the Docker container via the ./runtime:/app/runtime volume mount defined in docker-compose.yml.
Login Endpoint Limitations:
The /v1/auth/login API endpoint opens a browser window and requires a display environment. In Docker deployments:
- The container runs headlessly (
PLAYWRIGHT_HEADLESS=true) - No display server is available inside the container
- Therefore,
/v1/auth/loginwill fail with: "Headful interactive sign-in is unsupported in this headless container environment"
For Docker + Playwright authentication, always use verify_login.py on the host machine as documented above.
Monitor server output, request lifecycles, and session health logs:
docker logs -f web_ai_serverBecause the production-only container maps only persistent runtime state directories (./runtime) and does not bind-mount source code directories, any modification to Python source files (.py under src/ or app/) requires an image rebuild to be projected into the active container runtime:
docker compose up --buildormake build: Required whenever there are changes to Python source code, system packages, theDockerfile, or Python dependencies inrequirements.txt.make build-fresh: Recommended when troubleshooting package mismatch issues, resetting cached layers, or performing a clean verification of the dependency tree.
WARNING: The Playwright library version installed via
requirements.txt(e.g.,playwright==1.62.0) MUST match the browser driver versions packed inside the base image (mcr.microsoft.com/playwright/python:v1.62.0-noble). Mismatches between the library and driver versions can lead to runtime execution failures during browser automation.
Q: Where is authentication stored?
A: Authentication state is stored in runtime/auth/gemini.json on the host machine. The Docker container accesses this file via the ./runtime:/app/runtime volume mount defined in docker-compose.yml.
Q: Does authentication survive container recreation?
A: Yes. Because runtime/auth/gemini.json is stored in the ./runtime directory on the host (not inside the container), authentication persists across:
- Container restarts (
docker compose restart) - Container recreation (
docker compose down && docker compose up -d) - Image rebuilds (
make build)
Authentication is only lost if the ./runtime directory is deleted from the host machine.
Q: Can I generate authentication after starting the container?
A: Yes. Run poetry run python verify_login.py on your host machine, then restart the container with make stop && make up. The updated authentication state is picked up when the Docker container restarts, because Playwright loads runtime/auth/gemini.json only when creating a new browser context.
Note: Updating runtime/auth/gemini.json while the container is already running does not hot-reload the active Playwright context. Restart the container after re-running verify_login.py.