--- sidebar_position: 7 title: "Docker" description: "Running Hermes Agent in Docker and using Docker as a terminal backend" --- # Hermes Agent — Docker There are two distinct ways Docker intersects with Hermes Agent: 1. **Running Hermes IN Docker** — the agent itself runs inside a container (this page's primary focus) 2. **Docker as a terminal backend** — the agent runs on your host but executes commands inside a Docker sandbox (see [Configuration → terminal.backend](./configuration.md)) This page covers option 1. The container stores all user data (config, API keys, sessions, skills, memories) in a single directory mounted from the host at `/opt/data`. The image itself is stateless and can be upgraded by pulling a new version without losing any configuration. ## Quick start If this is your first time running Hermes Agent, create a data directory on the host and start the container interactively to run the setup wizard: ```sh mkdir -p ~/.hermes docker run -it --rm \ -v ~/.hermes:/opt/data \ nousresearch/hermes-agent ``` This drops you into the setup wizard, which will prompt you for your API keys and write them to `~/.hermes/.env`. You only need to do this once. It is highly recommended to set up a chat system for the gateway to work with at this point. ## Running in gateway mode Once configured, run the container in the background as a persistent gateway (Telegram, Discord, Slack, WhatsApp, etc.): ```sh docker run -d \ --name hermes \ --restart unless-stopped \ -v ~/.hermes:/opt/data \ nousresearch/hermes-agent gateway run ``` ## Running interactively (CLI chat) To open an interactive chat session against a running data directory: ```sh docker run -it --rm \ -v ~/.hermes:/opt/data \ nousresearch/hermes-agent ``` ## Persistent volumes The `/opt/data` volume is the single source of truth for all Hermes state. It maps to your host's `~/.hermes/` directory and contains: | Path | Contents | |------|----------| | `.env` | API keys and secrets | | `config.yaml` | All Hermes configuration | | `SOUL.md` | Agent personality/identity | | `sessions/` | Conversation history | | `memories/` | Persistent memory store | | `skills/` | Installed skills | | `cron/` | Scheduled job definitions | | `hooks/` | Event hooks | | `logs/` | Runtime logs | | `skins/` | Custom CLI skins | :::warning Never run two Hermes containers against the same data directory simultaneously — session files and memory stores are not designed for concurrent access. ::: ## Environment variable forwarding API keys are read from `/opt/data/.env` inside the container. You can also pass environment variables directly: ```sh docker run -it --rm \ -v ~/.hermes:/opt/data \ -e ANTHROPIC_API_KEY="sk-ant-..." \ -e OPENAI_API_KEY="sk-..." \ nousresearch/hermes-agent ``` Direct `-e` flags override values from `.env`. This is useful for CI/CD or secrets-manager integrations where you don't want keys on disk. ## Docker Compose example For persistent gateway deployment, a `docker-compose.yaml` is convenient: ```yaml version: "3.8" services: hermes: image: nousresearch/hermes-agent:latest container_name: hermes restart: unless-stopped command: gateway run volumes: - ~/.hermes:/opt/data # Uncomment to forward specific env vars instead of using .env file: # environment: # - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} # - OPENAI_API_KEY=${OPENAI_API_KEY} # - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} deploy: resources: limits: memory: 4G cpus: "2.0" ``` Start with `docker compose up -d` and view logs with `docker compose logs -f hermes`. ## Resource limits The Hermes container needs moderate resources. Recommended minimums: | Resource | Minimum | Recommended | |----------|---------|-------------| | Memory | 1 GB | 2–4 GB | | CPU | 1 core | 2 cores | | Disk (data volume) | 500 MB | 2+ GB (grows with sessions/skills) | Browser automation (Playwright/Chromium) is the most memory-hungry feature. If you don't need browser tools, 1 GB is sufficient. With browser tools active, allocate at least 2 GB. Set limits in Docker: ```sh docker run -d \ --name hermes \ --restart unless-stopped \ --memory=4g --cpus=2 \ -v ~/.hermes:/opt/data \ nousresearch/hermes-agent gateway run ``` ## What the Dockerfile does The official image is based on `debian:13.4` and includes: - Python 3 with all Hermes dependencies (`pip install -e ".[all]"`) - Node.js + npm (for browser automation and WhatsApp bridge) - Playwright with Chromium (`npx playwright install --with-deps chromium`) - ripgrep and ffmpeg as system utilities - The WhatsApp bridge (`scripts/whatsapp-bridge/`) The entrypoint script (`docker/entrypoint.sh`) bootstraps the data volume on first run: - Creates the directory structure (`sessions/`, `memories/`, `skills/`, etc.) - Copies `.env.example` → `.env` if no `.env` exists - Copies default `config.yaml` if missing - Copies default `SOUL.md` if missing - Syncs bundled skills using a manifest-based approach (preserves user edits) - Then runs `hermes` with whatever arguments you pass ## Upgrading Pull the latest image and recreate the container. Your data directory is untouched. ```sh docker pull nousresearch/hermes-agent:latest docker rm -f hermes docker run -d \ --name hermes \ --restart unless-stopped \ -v ~/.hermes:/opt/data \ nousresearch/hermes-agent gateway run ``` Or with Docker Compose: ```sh docker compose pull docker compose up -d ``` ## Skills and credential files When using Docker as the execution environment (not the methods above, but when the agent runs commands inside a Docker sandbox), Hermes automatically bind-mounts the skills directory (`~/.hermes/skills/`) and any credential files declared by skills into the container as read-only volumes. This means skill scripts, templates, and references are available inside the sandbox without manual configuration. The same syncing happens for SSH and Modal backends — skills and credential files are uploaded via rsync or the Modal mount API before each command. ## Troubleshooting ### Container exits immediately Check logs: `docker logs hermes`. Common causes: - Missing or invalid `.env` file — run interactively first to complete setup - Port conflicts if running with exposed ports ### "Permission denied" errors The container runs as root by default. If your host `~/.hermes/` was created by a non-root user, permissions should work. If you get errors, ensure the data directory is writable: ```sh chmod -R 755 ~/.hermes ``` ### Browser tools not working Playwright needs shared memory. Add `--shm-size=1g` to your Docker run command: ```sh docker run -d \ --name hermes \ --shm-size=1g \ -v ~/.hermes:/opt/data \ nousresearch/hermes-agent gateway run ``` ### Gateway not reconnecting after network issues The `--restart unless-stopped` flag handles most transient failures. If the gateway is stuck, restart the container: ```sh docker restart hermes ``` ### Checking container health ```sh docker logs --tail 50 hermes # Recent logs docker exec hermes hermes version # Verify version docker stats hermes # Resource usage ```