Hermes Agent - Docker
Docker는 Hermes Agent와 두 가지 방식으로 만납니다.
- Hermes를 Docker 안에서 실행 - agent 자체가 container 안에서 실행됩니다. 이 페이지의 주된 내용입니다.
- Docker를 terminal backend로 사용 - agent는 host에서 실행되지만 모든 command를 하나의 persistent Docker sandbox container 안에서 실행합니다. 이 container는 tool call,
/new, subagent를 지나 Hermes process가 살아 있는 동안 유지됩니다. 자세한 내용은 Configuration → Docker Backend를 참고하세요.
이 페이지는 1번을 다룹니다. container는 모든 user data(config, API key, session, skill, memory)를 host에서 /opt/data로 mount한 단일 directory에 저장합니다. image 자체는 stateless이므로, 새 version을 pull해 upgrade해도 configuration은 사라지지 않습니다.
빠른 시작
Hermes Agent를 처음 실행한다면 host에 data directory를 만들고, setup wizard를 실행하기 위해 container를 interactive mode로 시작합니다.
mkdir -p ~/.hermes
docker run -it --rm \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent setup
이 명령은 setup wizard로 들어갑니다. wizard는 API key를 묻고 ~/.hermes/.env에 기록합니다. 이 작업은 한 번만 하면 됩니다. 이 시점에서 gateway가 사용할 chat system도 함께 설정하는 것을 강력히 권장합니다.
gateway mode로 실행
설정이 끝나면 persistent gateway(Telegram, Discord, Slack, WhatsApp 등)로 container를 background에서 실행합니다.
docker run -d \
--name hermes \
--restart unless-stopped \
-v ~/.hermes:/opt/data \
-p 8642:8642 \
nousresearch/hermes-agent gateway run
port 8642는 gateway의 OpenAI-compatible API server와 health endpoint를 노출합니다. chat platform만 사용한다면 선택 사항이지만, dashboard나 external tool이 gateway에 접근해야 한다면 필요합니다.
참고: API server는 API_SERVER_ENABLED=true일 때만 켜집니다. container 안에서 127.0.0.1을 넘어 노출하려면 API_SERVER_HOST=0.0.0.0와 API_SERVER_KEY도 설정하세요. API_SERVER_KEY는 최소 8자여야 하며, openssl rand -hex 32로 생성할 수 있습니다. 예:
docker run -d \
--name hermes \
--restart unless-stopped \
-v ~/.hermes:/opt/data \
-p 8642:8642 \
-e API_SERVER_ENABLED=true \
-e API_SERVER_HOST=0.0.0.0 \
-e API_SERVER_KEY=your_api_key_here \
-e API_SERVER_CORS_ORIGINS='*' \
nousresearch/hermes-agent gateway run
internet-facing machine에서 port를 여는 것은 보안 위험입니다. 위험을 이해하지 못했다면 열지 마세요.
dashboard 실행
built-in web dashboard는 gateway와 같은 container 안에서 optional side-process로 실행됩니다. HERMES_DASHBOARD=1을 설정하고 gateway의 8642와 함께 9119 port를 노출합니다.
docker run -d \
--name hermes \
--restart unless-stopped \
-v ~/.hermes:/opt/data \
-p 8642:8642 \
-p 9119:9119 \
-e HERMES_DASHBOARD=1 \
nousresearch/hermes-agent gateway run
entrypoint는 main command를 exec하기 전에 background에서 hermes dashboard를 시작합니다. dashboard는 non-root hermes user로 실행됩니다. docker logs에서 dashboard output은 [dashboard] prefix가 붙으므로 gateway log와 구분하기 쉽습니다.
| Environment variable | Description | Default |
|---|---|---|
HERMES_DASHBOARD | main command와 함께 dashboard를 띄우려면 1(또는 true / yes)로 설정 | (unset - dashboard not started) |
HERMES_DASHBOARD_HOST | dashboard HTTP server bind address | 0.0.0.0 |
HERMES_DASHBOARD_PORT | dashboard HTTP server port | 9119 |
HERMES_DASHBOARD_TUI | in-browser Chat tab(PTY/WebSocket을 통한 embedded hermes --tui)을 노출하려면 1로 설정 | (unset) |
기본값 HERMES_DASHBOARD_HOST=0.0.0.0은 host가 published port를 통해 dashboard에 접근하려면 필요합니다. 이 경우 entrypoint는 자동으로 --insecure를 hermes dashboard에 전달합니다. dashboard를 container 내부 접근으로만 제한하고 싶다면(예: sidecar reverse proxy 뒤) 127.0.0.1로 override하세요.
dashboard side-process는 supervised되지 않습니다. crash되면 container가 restart될 때까지 내려간 상태로 남습니다. 별도 container로 dashboard를 실행하는 것은 지원하지 않습니다. dashboard의 gateway-liveness detection은 gateway process와 shared PID namespace가 필요합니다.
interactive 실행(CLI chat)
실행 중인 data directory를 대상으로 interactive chat session을 열려면:
docker run -it --rm \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent
이미 실행 중인 container 안에 terminal을 열었다면(예: Docker Desktop), 다음만 실행하면 됩니다.
/opt/hermes/.venv/bin/hermes
Persistent volumes
/opt/data volume은 모든 Hermes state의 single source of truth입니다. host의 ~/.hermes/ directory에 mapping되며 다음을 포함합니다.
| Path | Contents |
|---|---|
.env | API key와 secret |
config.yaml | 모든 Hermes configuration |
SOUL.md | agent personality/identity |
sessions/ | conversation history |
memories/ | persistent memory store |
skills/ | installed skills |
cron/ | scheduled job definition |
hooks/ | event hooks |
logs/ | runtime logs |
skins/ | custom CLI skins |
같은 data directory를 대상으로 Hermes gateway container 두 개를 동시에 실행하지 마세요. session file과 memory store는 concurrent write access를 전제로 설계되지 않았습니다.
Multi-profile support
Hermes는 multiple profiles를 지원합니다. profile은 별도 ~/.hermes/ directory이며, 하나의 설치에서 서로 독립적인 agent(SOUL, skill, memory, session, credential)를 실행할 수 있게 합니다. 하지만 Docker에서 실행할 때는 Hermes의 built-in multi-profile 기능을 권장하지 않습니다.
권장 pattern은 profile마다 container 하나를 두고, 각 container가 host의 고유 directory를 /opt/data로 bind-mount하는 것입니다.
# Work profile
docker run -d \
--name hermes-work \
--restart unless-stopped \
-v ~/.hermes-work:/opt/data \
-p 8642:8642 \
nousresearch/hermes-agent gateway run
# Personal profile
docker run -d \
--name hermes-personal \
--restart unless-stopped \
-v ~/.hermes-personal:/opt/data \
-p 8643:8642 \
nousresearch/hermes-agent gateway run
Docker에서는 profile보다 separate container가 나은 이유:
- Isolation - 각 container는 자체 filesystem, process table, resource limit을 갖습니다. 한 profile의 crash, dependency change, runaway session이 다른 profile에 영향을 주지 않습니다.
- Independent lifecycle - 각 agent를 따로 upgrade, restart, pause, roll back할 수 있습니다.
docker restart hermes-work는hermes-personal에 영향을 주지 않습니다. - Clean port and network separation - 각 gateway가 고유 host port에 bind합니다. chat platform이나 API server 사이에 cross-talk 위험이 없습니다.
- Simpler mental model - container 자체가 profile입니다. backup, migration, permission이 모두 bind-mounted directory를 따라가며, 추가
--profileflag를 기억할 필요가 없습니다. - Concurrent-write risk 회피 - 같은 data directory를 대상으로 gateway 두 개를 실행하지 말라는 위 warning은 single container 안의 profile에도 여전히 적용됩니다.
Docker Compose에서는 profile마다 service 하나를 선언하고 container_name, volumes, ports를 다르게 지정하면 됩니다.
services:
hermes-work:
image: nousresearch/hermes-agent:latest
container_name: hermes-work
restart: unless-stopped
command: gateway run
ports:
- "8642:8642"
volumes:
- ~/.hermes-work:/opt/data
hermes-personal:
image: nousresearch/hermes-agent:latest
container_name: hermes-personal
restart: unless-stopped
command: gateway run
ports:
- "8643:8642"
volumes:
- ~/.hermes-personal:/opt/data
environment variable forwarding
API key는 container 안의 /opt/data/.env에서 읽습니다. environment variable을 직접 전달할 수도 있습니다.
docker run -it --rm \
-v ~/.hermes:/opt/data \
-e ANTHROPIC_API_KEY="sk-ant-..." \
-e OPENAI_API_KEY="sk-..." \
nousresearch/hermes-agent
직접 전달한 -e flag는 .env의 값을 override합니다. key를 disk에 두고 싶지 않은 CI/CD나 secrets-manager integration에서 유용합니다.
Docker Compose 예제
gateway와 dashboard를 함께 persistent deployment로 운영하려면 docker-compose.yaml이 편리합니다.
services:
hermes:
image: nousresearch/hermes-agent:latest
container_name: hermes
restart: unless-stopped
command: gateway run
ports:
- "8642:8642" # gateway API
- "9119:9119" # dashboard (only reached when HERMES_DASHBOARD=1)
volumes:
- ~/.hermes:/opt/data
environment:
- HERMES_DASHBOARD=1
# Uncomment to forward specific env vars instead of using .env file:
# - 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"
docker compose up -d로 시작하고, docker compose logs -f로 log를 확인합니다. dashboard output은 [dashboard] prefix가 붙으므로 gateway log와 쉽게 구분됩니다.
resource limits
Hermes container는 중간 정도의 resource가 필요합니다. 권장 최소값:
| Resource | Minimum | Recommended |
|---|---|---|
| Memory | 1 GB | 2-4 GB |
| CPU | 1 core | 2 cores |
| Disk(data volume) | 500 MB | 2+ GB(session/skill이 쌓이며 증가) |
browser automation(Playwright/Chromium)이 가장 memory를 많이 쓰는 기능입니다. browser tool이 필요 없다면 1GB로 충분합니다. browser tool을 활성화한다면 최소 2GB를 할당하세요.
Docker에서 limit 설정:
docker run -d \
--name hermes \
--restart unless-stopped \
--memory=4g --cpus=2 \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent gateway run
Dockerfile이 하는 일
공식 image는 debian:13.4 기반이며 다음을 포함합니다.
- Python 3와 모든 Hermes dependency(
uv pip install -e ".[all]") - Node.js + npm(browser automation과 WhatsApp bridge용)
- Chromium이 포함된 Playwright(
npx playwright install --with-deps chromium --only-shell) - system utility로 ripgrep, ffmpeg, git, tini
docker-cli- container 안에서 실행되는 agent가 host Docker daemon을 drive할 수 있게 합니다. opt-in하려면/var/run/docker.sock을 bind-mount합니다.docker build,docker run, container inspection 등에 사용합니다.openssh-client- container 안에서 SSH terminal backend를 사용할 수 있게 합니다. SSH backend는 systemsshbinary를 shell out하므로, 이 패키지가 없으면 containerized install에서 조용히 실패했습니다.- WhatsApp bridge(
scripts/whatsapp-bridge/)
entrypoint script(docker/entrypoint.sh)는 첫 실행 때 data volume을 bootstrap합니다.
- directory structure(
sessions/,memories/,skills/등) 생성 .env가 없으면.env.example→.envcopyconfig.yaml이 없으면 default copySOUL.md가 없으면 default copy- manifest-based 방식으로 bundled skills sync(user edit 보존)
HERMES_DASHBOARD=1이면 background side-process로hermes dashboard실행(dashboard 실행 참고)- 그 뒤 사용자가 전달한 argument로
hermes실행
/opt/hermes/docker/entrypoint.sh를 command chain에 유지하지 않을 것이라면 image entrypoint를 override하지 마세요. entrypoint는 gateway state file이 생성되기 전에 root privilege를 hermes user로 낮춥니다. 공식 image 안에서 hermes gateway run을 root로 시작하는 것은 기본적으로 거부됩니다. /opt/data에 root-owned file을 남겨 이후 dashboard나 gateway start를 망가뜨릴 수 있기 때문입니다. 그 위험을 의도적으로 감수할 때만 HERMES_ALLOW_ROOT_GATEWAY=1을 설정하세요.
upgrading
latest image를 pull하고 container를 다시 만듭니다. data directory는 그대로 유지됩니다.
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
Docker Compose를 쓰면:
docker compose pull
docker compose up -d
skill 및 credential file
Docker를 execution environment로 사용할 때(위 방식들이 아니라, agent가 Docker sandbox 안에서 command를 실행하는 경우 - Configuration → Docker Backend 참고), Hermes는 모든 tool call에 하나의 long-lived container를 재사용합니다. 또한 skills directory(~/.hermes/skills/)와 skill이 선언한 credential file을 read-only volume으로 자동 bind-mount합니다. 따라서 skill script, template, reference가 별도 설정 없이 sandbox 안에서 사용 가능하며, container가 Hermes process lifetime 동안 유지되므로 설치한 dependency나 작성한 file이 다음 tool call에도 남아 있습니다.
SSH와 Modal backend에서도 같은 sync가 일어납니다. 각 command 전에 skill과 credential file이 rsync 또는 Modal mount API로 upload됩니다.
local inference server에 연결(vLLM, Ollama 등)
Hermes를 Docker에서 실행하고 inference server(vLLM, Ollama, text-generation-inference 등)는 host 또는 다른 container에서 실행하는 경우 networking에 특히 주의해야 합니다.
Docker Compose(권장)
두 service를 같은 Docker network에 둡니다. 가장 신뢰할 수 있는 방식입니다.
services:
vllm:
image: vllm/vllm-openai:latest
container_name: vllm
command: >
--model Qwen/Qwen2.5-7B-Instruct
--served-model-name my-model
--host 0.0.0.0
--port 8000
ports:
- "8000:8000"
networks:
- hermes-net
deploy:
resources:
reservations:
devices:
- capabilities: [gpu]
hermes:
image: nousresearch/hermes-agent:latest
container_name: hermes
restart: unless-stopped
command: gateway run
ports:
- "8642:8642"
volumes:
- ~/.hermes:/opt/data
networks:
- hermes-net
networks:
hermes-net:
driver: bridge
그런 다음 ~/.hermes/config.yaml에서 hostname으로 container name을 사용합니다.
model:
provider: custom
model: my-model
base_url: http://vllm:8000/v1
api_key: "none"
- hostname은
localhost나127.0.0.1이 아니라 container name(vllm)을 사용하세요.localhost는 Hermes container 자체를 가리킵니다. model값은 vLLM에 전달한--served-model-name과 일치해야 합니다.api_key는 비어 있지 않은 아무 문자열이면 됩니다. vLLM은 header를 요구하지만 기본적으로 값을 검증하지 않습니다.base_url끝에 trailing slash를 붙이지 마세요.
standalone Docker run(no Compose)
inference server가 Docker가 아니라 host에서 직접 실행 중이라면, macOS/Windows에서는 host.docker.internal을 사용하고 Linux에서는 --network host를 사용합니다.
macOS / Windows:
docker run -d \
--name hermes \
-v ~/.hermes:/opt/data \
-p 8642:8642 \
nousresearch/hermes-agent gateway run
# config.yaml
model:
provider: custom
model: my-model
base_url: http://host.docker.internal:8000/v1
api_key: "none"
Linux(host networking):
docker run -d \
--name hermes \
--network host \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent gateway run
# config.yaml
model:
provider: custom
model: my-model
base_url: http://127.0.0.1:8000/v1
api_key: "none"
--network host를 사용하면 -p flag는 무시됩니다. 모든 container port가 host에 직접 노출됩니다.
connectivity 확인
Hermes container 안에서 inference server에 접근 가능한지 확인합니다.
docker exec hermes curl -s http://vllm:8000/v1/models
served model list가 들어 있는 JSON response가 보여야 합니다. 실패하면 다음을 확인하세요.
- 두 container가 같은 Docker network에 있는지 확인합니다. (
docker network inspect hermes-net) - inference server가
127.0.0.1이 아니라0.0.0.0에서 listen 중인지 확인합니다. - port number가 일치하는지 확인합니다.
Ollama
Ollama도 같은 방식으로 동작합니다. Ollama가 host에서 실행 중이면 macOS/Windows에서는 host.docker.internal:11434, Linux에서는 --network host와 127.0.0.1:11434를 사용합니다. Ollama가 같은 Docker network의 자체 container에서 실행 중이라면:
model:
provider: custom
model: llama3
base_url: http://ollama:11434/v1
api_key: "none"
문제 해결
container가 즉시 종료됨
log를 확인하세요. docker logs hermes 일반적인 원인:
.envfile이 없거나 잘못됨 - 먼저 interactive mode로 실행해 setup을 완료하세요.- 노출된 port가 충돌함
"Permission denied" 오류
container entrypoint는 gosu를 통해 non-root hermes user(UID 10000)로 privilege를 낮춥니다. host의 ~/.hermes/가 다른 UID 소유라면 HERMES_UID/HERMES_GID를 host user에 맞추거나, data directory가 writable인지 확인하세요.
chmod -R 755 ~/.hermes
browser tool이 작동하지 않음
Playwright는 shared memory가 필요합니다. Docker run command에 --shm-size=1g를 추가하세요.
docker run -d \
--name hermes \
--shm-size=1g \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent gateway run
network issue 뒤 gateway가 다시 연결되지 않음
--restart unless-stopped flag가 대부분의 transient failure를 처리합니다. gateway가 stuck 상태라면 container를 재시작하세요.
docker restart hermes
container health 확인
docker logs --tail 50 hermes # Recent logs
docker run -it --rm nousresearch/hermes-agent:latest version # Verify version
docker stats hermes # Resource usage