Docker Deployment: Run PocketPaw in Containers
PocketPaw ships with a production-ready Dockerfile and docker-compose.yml in the repository root. The Docker image includes all extras ([all]), Playwright Chromium, tesseract OCR, Node.js with the Claude Code CLI and Codex CLI — everything works out of the box.
Quick Start
# Clone the repogit clone https://github.com/pocketpaw/pocketpaw.gitcd pocketpaw
# Copy the env template and fill in your keyscp .env.example .env
# Build and startdocker compose up -dThe dashboard is available at http://localhost:8888.
Docker’s bridge networking means localhost auth bypass doesn’t work inside a container. You’ll need to log in with the access token.
Get the access token and paste it into the login page:
docker exec pocketpaw cat /home/pocketpaw/.pocketpaw/access_tokenDockerfile Overview
The Dockerfile uses a multi-stage build for a lean runtime image:
Builder stage (python:3.12-slim):
- Installs build dependencies (
gcc,python3-dev,git) - Creates a virtual environment and installs
pocketpaw[all] - Downloads Playwright Chromium
Node stage (node:22-slim):
- Installs Claude Code CLI (
@anthropic-ai/claude-code) and Codex CLI (@openai/codex) globally
Runtime stage (python:3.12-slim):
- Installs only runtime system deps (tesseract, Chromium shared libs, curl)
- Copies Node.js binary and global packages from the node stage (no
curl | bash) - Copies the venv and Playwright browsers from the builder
- Creates a
/home/pocketpaw/workspacedirectory for agent-created files - Runs as a non-root
pocketpawuser - Exposes port
8888with a healthcheck
The container binds to 0.0.0.0:8888 by default (set via POCKETPAW_WEB_HOST and POCKETPAW_WEB_PORT environment variables in the Dockerfile).
The Node.js layer (runtime + Claude Code CLI + Codex CLI) adds roughly 200 MB to the image. If you don’t need the claude_agent_sdk or codex_cli Docker-native CLI backends and want a smaller image, you can remove the node stage and the corresponding COPY --from=node lines in the Dockerfile.
Docker Compose
The docker-compose.yml defines three services. Only the main pocketpaw service starts by default — Ollama and Qdrant are behind Compose profiles.
Default (PocketPaw only)
docker compose up -dWith Ollama (local LLM)
Option A: Ollama in Docker (via Compose profile)
docker compose --profile ollama up -dSet the Ollama host to the container service name in your .env:
POCKETPAW_OLLAMA_HOST=http://ollama:11434Then pull the models you need:
docker compose exec ollama ollama pull llama3.2docker compose exec ollama ollama pull nomic-embed-textFor GPU passthrough with NVIDIA, uncomment the deploy.resources.reservations block in docker-compose.yml.
Option B: Ollama on the host
If Ollama is already running on your host machine (outside Docker), the container can reach it via host.docker.internal — this is configured automatically in docker-compose.yml via extra_hosts. Set in your .env:
POCKETPAW_OLLAMA_HOST=http://host.docker.internal:11434The default http://localhost:11434 won’t work from inside a container — localhost inside the container refers to the container itself, not your host machine.
With Qdrant (vector memory)
docker compose --profile qdrant up -dQdrant is needed for Mem0 semantic memory. It exposes port 6333 for the REST API.
All services
docker compose --profile ollama --profile qdrant up -dEnvironment Variables
All configuration is passed via environment variables. Copy .env.example to .env and fill in the values you need:
cp .env.example .envThe .env.example file is organized by section (LLM, channels, memory, tools, security) and documents every available POCKETPAW_ variable. See the Configuration reference for full details.
You can also change the host port:
POCKETPAW_PORT=9000 docker compose up -dPersistent Data
Two volumes are mounted:
Config & memory — named volume pocketpaw-data at /home/pocketpaw/.pocketpaw:
- Configuration (
config.json,secrets.enc) - Session history
- Memory data (file-based and Mem0)
- OAuth tokens
- Audit logs
- MCP server configs
- Skills
Workspace — bind mount ./workspace at /home/pocketpaw/workspace:
- Files created by the agent via Write, Bash, or other tools
- Directly accessible on the host at
./workspace/next to yourdocker-compose.yml - The
POCKETPAW_FILE_JAIL_PATHenv var is set automatically in the image
Data survives docker compose down and docker compose up cycles. To fully reset, remove the named volume:
docker compose down -vTo customize the workspace path on the host, edit the bind mount in docker-compose.yml:
volumes: - /your/preferred/path:/home/pocketpaw/workspaceManaging the Container
# View logsdocker compose logs -f pocketpaw
# Restartdocker compose restart pocketpaw
# Stop everythingdocker compose down
# Rebuild after pulling updatesgit pull && docker compose build && docker compose up -dBrowser Automation
Playwright Chromium is included in the Docker image along with all required shared libraries. Browser tools work out of the box inside the container — no additional setup needed.
Claude Code OAuth Support
The Docker image includes the Claude Code CLI pre-installed. You can authenticate using an OAuth token from your Claude Max or Pro plan instead of a separate API key.
Option 1: OAuth token (recommended for remote/Coolify deployments):
# Generate a long-lived token on your local machineclaude setup-token
# Add to .envPOCKETPAW_CLAUDE_SDK_PROVIDER=claude_codePOCKETPAW_CLAUDE_CODE_OAUTH_TOKEN={"accessToken":"sk-ant-oat01-...","refreshToken":"sk-ant-ort01-...","expiresAt":"2027-..."}Option 2: CLI interactive login (persisted in a volume):
Mount a volume to /home/pocketpaw/.claude, exec into the container, run claude, and complete the browser-based login once. Credentials persist across restarts.
See the Discord Docker guide for detailed instructions on both options.
Discord-Only Deployment
For a lightweight, headless Discord bot without the web dashboard, use the dedicated setup in deploy/discord/. It has a smaller image (no Playwright/Chromium), its own Dockerfile, and compose file optimized for single-channel operation.
See Discord Docker Deployment for the full guide.
Limitations
- Desktop tools (
pyautogui) require a display server and won’t work in a headless container. They fail gracefully at invocation time. - WhatsApp Personal mode (neonize QR pairing) requires a persistent session. The named volume handles this, but the QR code must be scanned via the web dashboard on first setup.
- Copilot SDK backend requires the
copilotGo binary which is not bundled in the image. Install it manually if needed.
Related
Self-Hosting
Reverse proxy, SSL, and production hardening for your PocketPaw server.
Systemd Service
Run PocketPaw as a background daemon without Docker on Linux.
Configuration
Full reference for all PocketPaw environment variables and config options.
Discord Docker
Lightweight headless Discord bot deployment with Claude Code OAuth.