Hermes Agent — Docker
Есть два различных способа использования Docker с Hermes Agent:
-
Запуск Hermes В Docker — сам агент работает внутри контейнера (основная тема этой страницы)
-
Docker как терминальный backend — агент работает на вашем хосте, но выполняет каждую команду внутри единого постоянного Docker-контейнера-песочницы, который сохраняется между вызовами инструментов,
/newи сабагентами на время жизни процесса Hermes (см. Configuration → Docker Backend)
Эта страница описывает вариант 1. Контейнер хранит все пользовательские данные (конфигурацию, API-ключи, сессии, skills, воспоминания) в одной директории, смонтированной с хоста по пути /opt/data. Сам образ не имеет состояния и может быть обновлён путём загрузки новой версии без потери конфигурации.
Быстрый старт
Если вы запускаете Hermes Agent впервые, создайте директорию для данных на хосте и запустите контейнер в интерактивном режиме для работы мастера настройки:
mkdir -p ~/.hermes
docker run -it --rm \\
-v ~/.hermes:/opt/data \\
nousresearch/hermes-agent setup
Это запустит мастер настройки, который запросит ваши API-ключи и запишет их в ~/.hermes/.env. Это нужно сделать только один раз. Настоятельно рекомендуется на этом этапе настроить чат-систему для работы шлюза.
Запуск в режиме шлюза
После настройки запустите контейнер в фоновом режиме как постоянный шлюз (Telegram, Discord, Slack, WhatsApp и т.д.):
docker run -d \\
--name hermes \\
--restart unless-stopped \\
-v ~/.hermes:/opt/data \\
-p 8642:8642 \\
nousresearch/hermes-agent gateway run
Порт 8642 открывает доступ к OpenAI-совместимому API серверу и endpoint-у для проверки здоровья шлюза. Это необязательно, если вы используете только чат-платформы (Telegram, Discord и т.д.), но требуется для работы панели управления или внешних инструментов, обращающихся к шлюзу.
Примечание: API-сервер включается только при API_SERVER_ENABLED=true. Чтобы открыть доступ к нему за пределами 127.0.0.1 внутри контейнера, также установите API_SERVER_HOST=0.0.0.0 и 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
Открытие любого порта на машине, подключённой к интернету, представляет угрозу безопасности. Не делайте этого, если не понимаете связанные риски.
Запуск панели управления
Встроенная веб-панель управления запускается как опциональный фоновый процесс внутри того же контейнера, что и шлюз. Установите HERMES_DASHBOARD=1 и откройте порт 9119 вместе с портом шлюза 8642:
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
Точка входа запускает hermes dashboard в фоне (от имени непривилегированного пользователя hermes) перед exec основной команды. Вывод панели управления помечается префиксом [dashboard] в docker logs, что позволяет легко отделить его от логов шлюза.
| Переменная окружения | Описание | По умолчанию |
|---|---|---|
HERMES_DASHBOARD |
Установите в 1 (или true / yes), чтобы запустить панель управления вместе с основной командой |
(не установлена — панель не запускается) |
HERMES_DASHBOARD_HOST |
Адрес привязки HTTP-сервера панели управления | 0.0.0.0 |
HERMES_DASHBOARD_PORT |
Порт HTTP-сервера панели управления | 9119 |
HERMES_DASHBOARD_TUI |
Установите в 1, чтобы открыть вкладку чата в браузере (встроенный hermes --tui через PTY/WebSocket) |
(не установлена) |
Значение по умолчанию HERMES_DASHBOARD_HOST=0.0.0.0 необходимо, чтобы хост мог обращаться к панели управления через опубликованный порт; точка входа автоматически передаёт флаг --insecure в hermes dashboard в этом случае. Замените на 127.0.0.1, если хотите ограничить доступ к панели управления только изнутри контейнера (например, за обратным прокси в sidecar-контейнере).
Интерактивный запуск (CLI чат)
Чтобы открыть интерактивную чат-сессию с существующей директорией данных:
docker run -it --rm \\
-v ~/.hermes:/opt/data \\
nousresearch/hermes-agent
Или, если вы уже открыли терминал в запущенном контейнере (например, через Docker Desktop), просто выполните:
/opt/hermes/.venv/bin/hermes
Постоянные тома
Том /opt/data является единым источником истины для всего состояния Hermes. Он соответствует директории ~/.hermes/ на вашем хосте и содержит:
| Путь | Содержимое |
|---|---|
.env |
API-ключи и секреты |
config.yaml |
Вся конфигурация Hermes |
SOUL.md |
Личность/идентичность агента |
sessions/ |
История разговоров |
memories/ |
Постоянное хранилище воспоминаний |
skills/ |
Установленные навыки |
cron/ |
Определения запланированных задач |
hooks/ |
Событийные хуки |
logs/ |
Логи выполнения |
skins/ |
Пользовательские темы CLI |
Поддержка нескольких профилей
Hermes поддерживает несколько профилей — отдельные директории ~/.hermes/, позволяющие запускать независимых агентов (разные SOUL, навыки, память, сессии, учётные данные) из одной установки. При работе под Docker использовать встроенную функцию множественных профилей Hermes не рекомендуется.
Вместо этого рекомендуется подход один контейнер на профиль, где каждый контейнер монтирует свою собственную директорию хоста как /opt/data:
# Рабочий профиль
docker run -d \\
--name hermes-work \\
--restart unless-stopped \\
-v ~/.hermes-work:/opt/data \\
-p 8642:8642 \\
nousresearch/hermes-agent gateway run
# Личный профиль
docker run -d \\
--name hermes-personal \\
--restart unless-stopped \\
-v ~/.hermes-personal:/opt/data \\
-p 8643:8642 \\
nousresearch/hermes-agent gateway run
Почему отдельные контейнеры лучше профилей в Docker:
-
Изоляция — каждый контейнер имеет свою файловую систему, таблицу процессов и ограничения ресурсов. Сбой, изменение зависимостей или вышедшая из-под контроля сессия в одном профиле не могут повлиять на другой.
-
Независимый жизненный цикл — обновляйте, перезапускайте, приостанавливайте или откатывайте каждого агента отдельно (
docker restart hermes-workне затрагиваетhermes-personal). -
Чистое разделение портов и сети — каждый шлюз привязывается к своему порту хоста; отсутствует риск пересечения чат-платформ или API-серверов.
-
Более простая ментальная модель — контейнер является профилем. Резервное копирование, миграция и права доступа следуют за смонтированной директорией, без необходимости запоминать дополнительные флаги
--profile. -
Избежание риска одновременной записи — предупреждение выше о недопустимости запуска двух шлюзов против одной директории данных также относится к профилям внутри одного контейнера.
В Docker Compose это означает объявление одного сервиса на профиль с отдельными 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
Проброс переменных окружения
API-ключи считываются из /opt/data/.env внутри контейнера. Вы также можете передавать переменные окружения напрямую:
docker run -it --rm \\
-v ~/.hermes:/opt/data \\
-e ANTHROPIC_API_KEY="sk-ant-..." \\
-e OPENAI_API_KEY="sk-..." \\
nousresearch/hermes-agent
Флаги -e напрямую переопределяют значения из .env. Это удобно для CI/CD или интеграций с менеджерами секретов, когда не нужно хранить ключи на диске.
Пример Docker Compose
Для постоянного развёртывания со шлюзом и панелью управления удобно использовать docker-compose.yaml:
services:
hermes:
image: nousresearch/hermes-agent:latest
container_name: hermes
restart: unless-stopped
command: gateway run
ports:
- "8642:8642" # API шлюза
- "9119:9119" # панель управления (доступна только при HERMES_DASHBOARD=1)
volumes:
- ~/.hermes:/opt/data
environment:
- HERMES_DASHBOARD=1
# Раскомментируйте для проброса конкретных переменных окружения вместо использования .env:
# - 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. Вывод панели управления помечается префиксом [dashboard], что позволяет легко отфильтровать его от логов шлюза.
Ограничения ресурсов
Контейнеру Hermes требуются умеренные ресурсы. Рекомендуемые минимумы:
| Ресурс | Минимум | Рекомендуется |
|---|---|---|
| Память | 1 ГБ | 2–4 ГБ |
| CPU | 1 ядро | 2 ядра |
| Диск (том данных) | 500 МБ | 2+ ГБ (растёт с сессиями/skills) |
Автоматизация браузера (Playwright/Chromium) — самая требовательная к памяти функция. Если вам не нужны инструменты браузера, достаточно 1 ГБ. При активных инструментах браузера выделите не менее 2 ГБ.
Установите лимиты в Docker:
docker run -d \\
--name hermes \\
--restart unless-stopped \\
--memory=4g --cpus=2 \\
-v ~/.hermes:/opt/data \\
nousresearch/hermes-agent gateway run
Что делает Dockerfile
Официальный образ основан на debian:13.4 и включает:
-
Python 3 со всеми зависимостями Hermes (
uv pip install -e ".[all]") -
Node.js + npm (для автоматизации браузера и моста WhatsApp)
-
Playwright с Chromium (
npx playwright install --with-deps chromium --only-shell) -
ripgrep, ffmpeg, git и tini как системные утилиты
-
docker-cli— чтобы агенты, работающие внутри контейнера, могли управлять Docker-демоном хоста (подключите/var/run/docker.sockдля включения) дляdocker build,docker run, инспекции контейнеров и т.д. -
openssh-client— включает SSH терминальный backend изнутри контейнера. SSH backend использует системный бинарникssh; без этого пакета он молча не работал в контейнеризированных установках. -
Мост WhatsApp (
scripts/whatsapp-bridge/)
Скрипт точки входа (docker/entrypoint.sh) инициализирует том данных при первом запуске:
-
Создаёт структуру директорий (
sessions/,memories/,skills/и т.д.) -
Копирует
.env.example→.env, если.envне существует -
Копирует
config.yamlпо умолчанию, если отсутствует -
Копирует
SOUL.mdпо умолчанию, если отсутствует -
Синхронизирует встроенные навыки с помощью подхода на основе манифеста (сохраняет пользовательские изменения)
-
Опционально запускает
hermes dashboardкак фоновый процесс приHERMES_DASHBOARD=1(см. Запуск панели управления) -
Затем запускает
hermesс переданными аргументами
Обновление
Загрузите последний образ и пересоздайте контейнер. Ваша директория данных останется нетронутой.
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
Skills и файлы учётных данных
При использовании Docker в качестве среды выполнения (не описанными выше методами, а когда агент выполняет команды внутри Docker-песочницы — см. Configuration → Docker Backend), Hermes повторно использует один долгоживущий контейнер для всех вызовов инструментов и автоматически монтирует директорию навыков (~/.hermes/skills/) и любые файлы учётных данных, объявленные навыками, в этот контейнер как тома только для чтения. Скрипты навыков, шаблоны и ссылки доступны внутри песочницы без ручной настройки, а поскольку контейнер сохраняется на время жизни процесса Hermes, любые установленные зависимости или созданные файлы остаются доступными для следующего вызова инструмента.
Та же синхронизация происходит для backend-ов SSH и Modal — навыки и файлы учётных данных загружаются через rsync или Modal mount API перед каждой командой.
Подключение к локальным серверам инференса (vLLM, Ollama и др.)
При запуске Hermes в Docker, когда ваш сервер инференса (vLLM, Ollama, text-generation-inference и т.д.) также работает на хосте или в другом контейнере, настройка сети требует дополнительного внимания.
Docker Compose (рекомендуется)
Поместите оба сервиса в одну сеть Docker. Это самый надёжный подход:
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 используйте имя контейнера в качестве имени хоста:
model:
provider: custom
model: my-model
base_url: http://vllm:8000/v1
api_key: "none"
Ключевые моменты
-
Используйте имя контейнера (
vllm) в качестве имени хоста — неlocalhostили127.0.0.1, которые ссылаются на сам контейнер Hermes. -
Значение
modelдолжно соответствовать--served-model-name, переданному vLLM. -
Установите
api_keyв любую непустую строку (vLLM требует заголовок, но по умолчанию его не проверяет). -
Не добавляйте косую черту в конце
base_url.
Самостоятельный Docker run (без Compose)
Если ваш сервер инференса работает непосредственно на хосте (не в Docker), используйте host.docker.internal на macOS/Windows или --network host на Linux:
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 (сетевое взаимодействие хоста):
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 игнорируется — все порты контейнера напрямую открываются на хосте.
Проверка подключения
Изнутри контейнера Hermes убедитесь, что сервер инференса доступен:
docker exec hermes curl -s http://vllm:8000/v1/models
Вы должны увидеть JSON-ответ со списком вашей модели. Если это не сработало, проверьте:
-
Оба контейнера находятся в одной сети Docker (
docker network inspect hermes-net) -
Сервер инференса слушает на
0.0.0.0, а не на127.0.0.1 -
Номер порта совпадает
Ollama
Ollama работает аналогично. Если Ollama запущен на хосте, используйте host.docker.internal:11434 (macOS/Windows) или 127.0.0.1:11434 (Linux с --network host). Если Ollama работает в своём контейнере в той же сети Docker:
model:
provider: custom
model: llama3
base_url: http://ollama:11434/v1
api_key: "none"
Устранение неполадок
Контейнер сразу завершает работу
Проверьте логи: docker logs hermes. Частые причины:
-
Отсутствует или некорректен файл
.env— сначала запустите интерактивно для завершения настройки -
Конфликт портов при запуске с открытыми портами
Ошибки «Отказано в доступе»
Точка входа контейнера понижает привилегии до непривилегированного пользователя hermes (UID 10000) через gosu. Если ваша директория ~/.hermes/ на хосте принадлежит другому UID, установите HERMES_UID/HERMES_GID в соответствии с вашим пользователем хоста или убедитесь, что директория данных доступна для записи:
chmod -R 755 ~/.hermes
Инструменты браузера не работают
Playwright требует разделяемую память. Добавьте --shm-size=1g в команду Docker run:
docker run -d \\
--name hermes \\
--shm-size=1g \\
-v ~/.hermes:/opt/data \\
nousresearch/hermes-agent gateway run
Шлюз не переподключается после сетевых проблем
Флаг --restart unless-stopped обрабатывает большинство временных сбоев. Если шлюз завис, перезапустите контейнер:
docker restart hermes
Проверка здоровья контейнера
docker logs --tail 50 hermes # Последние логи
docker run -it --rm nousresearch/hermes-agent:latest version # Проверка версии
docker stats hermes # Использование ресурсов