Files
pocketpaw/docs/deployment/docker.mdx
Rohit Kushwaha d2dc43aeeb docs(discord): add Discord Docker deployment guide and update Discord docs
- Add new deployment/discord-docker.mdx with full Docker setup guide
  (LLM provider tabs, Claude Code OAuth, Coolify, volume config)
- Update channels/discord.mdx with missing config vars (conversation
  all channels, exclude channels, status, activity), Message Content
  Intent, server-wide conversation mode, bot presence section
- Update guides/discord-ai-bot.mdx with Docker deployment and
  server-wide conversation mode
- Update deployment/docker.mdx with Claude Code OAuth section and
  Discord-only deployment reference
- Add Discord Docker to sidebar navigation in docs-config.json
2026-03-21 00:30:29 +05:30

245 lines
8.3 KiB
Plaintext

---
title: "Docker Deployment: Run PocketPaw in Containers"
description: "Run PocketPaw in Docker with the included Dockerfile and docker-compose.yml. Multi-stage build, non-root user, Playwright browser support, and optional Ollama and Qdrant via Compose profiles."
section: Deployment
ogType: article
keywords: ["docker", "container", "docker-compose", "dockerfile", "containerized ai"]
tags: ["deployment", "docker"]
---
# 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
```bash
# Clone the repo
git clone https://github.com/pocketpaw/pocketpaw.git
cd pocketpaw
# Copy the env template and fill in your keys
cp .env.example .env
# Build and start
docker compose up -d
```
The dashboard is available at `http://localhost:8888`.
<Callout type="warning">
Docker's bridge networking means localhost auth bypass doesn't work inside a container. You'll need to log in with the access token.
</Callout>
Get the access token and paste it into the login page:
```bash
docker exec pocketpaw cat /home/pocketpaw/.pocketpaw/access_token
```
## Dockerfile 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/workspace` directory for agent-created files
- Runs as a non-root `pocketpaw` user
- Exposes port `8888` with a healthcheck
<Callout type="info">
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).
</Callout>
<Callout type="tip">
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.
</Callout>
## Docker Compose
The `docker-compose.yml` defines three services. Only the main `pocketpaw` service starts by default -- Ollama and Qdrant are behind [Compose profiles](https://docs.docker.com/compose/profiles/).
### Default (PocketPaw only)
```bash
docker compose up -d
```
### With Ollama (local LLM)
**Option A: Ollama in Docker** (via Compose profile)
```bash
docker compose --profile ollama up -d
```
Set the Ollama host to the container service name in your `.env`:
```bash
POCKETPAW_OLLAMA_HOST=http://ollama:11434
```
Then pull the models you need:
```bash
docker compose exec ollama ollama pull llama3.2
docker compose exec ollama ollama pull nomic-embed-text
```
<Callout type="tip">
For GPU passthrough with NVIDIA, uncomment the `deploy.resources.reservations` block in `docker-compose.yml`.
</Callout>
**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`:
```bash
POCKETPAW_OLLAMA_HOST=http://host.docker.internal:11434
```
<Callout type="warning">
The default `http://localhost:11434` won't work from inside a container -- `localhost` inside the container refers to the container itself, not your host machine.
</Callout>
### With Qdrant (vector memory)
```bash
docker compose --profile qdrant up -d
```
Qdrant is needed for Mem0 semantic memory. It exposes port `6333` for the REST API.
### All services
```bash
docker compose --profile ollama --profile qdrant up -d
```
## Environment Variables
All configuration is passed via environment variables. Copy `.env.example` to `.env` and fill in the values you need:
```bash
cp .env.example .env
```
The `.env.example` file is organized by section (LLM, channels, memory, tools, security) and documents every available `POCKETPAW_` variable. See the [Configuration reference](/getting-started/configuration) for full details.
You can also change the host port:
```bash
POCKETPAW_PORT=9000 docker compose up -d
```
## Persistent 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 your `docker-compose.yml`
- The `POCKETPAW_FILE_JAIL_PATH` env var is set automatically in the image
Data survives `docker compose down` and `docker compose up` cycles. To fully reset, remove the named volume:
```bash
docker compose down -v
```
To customize the workspace path on the host, edit the bind mount in `docker-compose.yml`:
```yaml
volumes:
- /your/preferred/path:/home/pocketpaw/workspace
```
## Managing the Container
```bash
# View logs
docker compose logs -f pocketpaw
# Restart
docker compose restart pocketpaw
# Stop everything
docker compose down
# Rebuild after pulling updates
git pull && docker compose build && docker compose up -d
```
## Browser 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):
```bash
# Generate a long-lived token on your local machine
claude setup-token
# Add to .env
POCKETPAW_CLAUDE_SDK_PROVIDER=claude_code
POCKETPAW_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](/deployment/discord-docker) 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](/deployment/discord-docker) 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 `copilot` Go binary which is not bundled in the image. Install it manually if needed.
## Related
<CardGroup>
<Card title="Self-Hosting" icon="lucide:server" href="/deployment/self-hosting">
Reverse proxy, SSL, and production hardening for your PocketPaw server.
</Card>
<Card title="Systemd Service" icon="lucide:terminal" href="/deployment/systemd">
Run PocketPaw as a background daemon without Docker on Linux.
</Card>
<Card title="Configuration" icon="lucide:settings" href="/getting-started/configuration">
Full reference for all PocketPaw environment variables and config options.
</Card>
<Card title="Discord Docker" icon="lucide:gamepad-2" href="/deployment/discord-docker">
Lightweight headless Discord bot deployment with Claude Code OAuth.
</Card>
</CardGroup>