Skip to content

Docker Deployment

Docker is the fastest way to get a reproducible Snippbot deployment. This guide covers the complete docker-compose.yml setup, first-run configuration, and ongoing maintenance commands.

  • Docker 24+ and Docker Compose v2 (the docker compose plugin, not the legacy docker-compose binary)
  • An Anthropic API key (or other supported provider key)

Create a file named docker-compose.yml in a directory of your choice (e.g. ~/snippbot/):

docker-compose.yml
services:
snippbot:
image: ghcr.io/snippbot/snippbot:latest
container_name: snippbot
restart: unless-stopped
ports:
- "18781:18781"
- "18790:18790"
volumes:
- snippbot-data:/root/.snippbot
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- SNIPPBOT_HOST=0.0.0.0
- SNIPPBOT_PORT=18781
- SNIPPBOT_LOG_LEVEL=info
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:18781/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 15s
volumes:
snippbot-data:
driver: local

Create a .env file in the same directory to hold your secrets:

.env
ANTHROPIC_API_KEY=sk-ant-your-key-here

Docker Compose automatically reads .env from the current directory and substitutes variables in docker-compose.yml.

VariableRequiredDefaultDescription
ANTHROPIC_API_KEYYes*Anthropic API key for Claude models
OPENAI_API_KEYNoOpenAI API key (if using OpenAI models)
SNIPPBOT_HOSTNo127.0.0.1Host address to bind the server to; set to 0.0.0.0 inside Docker
SNIPPBOT_PORTNo18781Port for the API and UI
SNIPPBOT_LOG_LEVELNoinfoLogging verbosity: debug, info, warning, error
SNIPPBOT_SECRET_KEYNoauto-generatedSecret key for session signing; set explicitly for multi-instance deployments

*Required unless another provider key is configured.


  1. Start the container

    Start in detached mode
    docker compose up -d

    Docker pulls the image (first run only) and starts the container. The -d flag runs it in the background.

  2. Complete first-run setup

    Open your browser and visit:

    http://localhost:18781/setup

    The setup wizard guides you through:

    • Creating your admin account
    • Confirming your API key is working
    • Creating your first agent
  3. Verify the health check

    Check container health
    docker compose ps

    The STATUS column should show Up (healthy) after about 30 seconds.


All Snippbot data (the SQLite database, agent workspaces, config files, and uploaded files) is stored in the named volume snippbot-data, which maps to /root/.snippbot inside the container.

To find where Docker stores the volume on your host:

Terminal window
docker volume inspect snippbot_snippbot-data
Backup the data volume to a tar file
docker run --rm \
-v snippbot_snippbot-data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/snippbot-backup-$(date +%Y%m%d).tar.gz -C /data .
Restore from a backup tar file
docker compose down
docker run --rm \
-v snippbot_snippbot-data:/data \
-v $(pwd):/backup \
alpine sh -c "rm -rf /data/* && tar xzf /backup/snippbot-backup-20260301.tar.gz -C /data"
docker compose up -d

Pull the latest image and restart
docker compose pull && docker compose up -d

This downloads the latest image and recreates the container with zero data loss. The snippbot-data volume persists across container recreation.


Follow live logs
docker compose logs -f snippbot
View last 100 lines
docker compose logs --tail=100 snippbot
Open a bash shell
docker compose exec snippbot bash

This gives you a shell where you can run snippbot CLI commands directly:

Terminal window
snippbot status
snippbot config show
Stop without removing data
docker compose down
Stop and remove data volume (destructive)
docker compose down -v

The channel adapter runs as a separate process inside the same container. Port 18790 is already mapped in the docker-compose.yml above. To start the adapter:

Start the channel adapter inside the container
docker compose exec snippbot snippbot channel start

Or add it as a second service that shares the same data volume:

docker-compose.yml (with channel adapter as separate service)
services:
snippbot:
image: ghcr.io/snippbot/snippbot:latest
# ... (same as above)
snippbot-channels:
image: ghcr.io/snippbot/snippbot:latest
container_name: snippbot-channels
restart: unless-stopped
command: ["snippbot", "channel", "start"]
ports:
- "18790:18790"
volumes:
- snippbot-data:/root/.snippbot
environment:
- SNIPPBOT_HOST=0.0.0.0
depends_on:
snippbot:
condition: service_healthy
volumes:
snippbot-data:

For production, place Snippbot behind nginx or Caddy to handle HTTPS. See the Reverse Proxy guide for complete configuration examples.

The key change is to not expose port 18781 publicly — let your reverse proxy handle TLS and proxy traffic internally:

docker-compose.yml (proxy-only port binding)
ports:
- "127.0.0.1:18781:18781" # Only accessible on localhost
- "127.0.0.1:18790:18790" # Channel adapter, localhost only