Hermes Agent Docker 本番運用完全ガイド|永続ボリューム / Compose / s6 設計【2026年版】

Hermes Agent Docker 本番運用完全ガイド|永続ボリューム / Compose / s6 設計【2026年版】

株式会社FyveではAIエージェント基盤の構築支援を行っており、Hermes Agentを本番で常駐運用したいという相談が、ここ数ヶ月で明らかに増えました。中でも一番多いのが「Dockerで動かしているはずなのに、再起動するとMEMORY.mdが消える」「コンテナ内でファイルを書こうとするとPermission deniedになる」という2大トラブルです。

どちらもGitHub Issueで報告されている既知の問題で、設計段階で押さえておけば回避できます。この記事では、私たちが実案件で組んでいるDocker構成を、docker-compose.ymlの実例と一緒に最初から最後まで通しで解説します。永続ボリューム、HERMES_UID、s6-overlayによる複数プロセス管理、TLSリバースプロキシまで含めた、本番で耐える構成です。

なぜDockerでHermes Agentを運用するのか

Hermes AgentをDockerで運用する4つのメリット(再現性・隔離・デプロイ容易性・セキュリティ監査対応)

Hermes Agentはローカル実行でも動きますが、本番でクライアント業務に組み込むとなると、ホストOSに直接インストールする運用はすぐに限界が来ます。Node.jsのバージョン、Pythonのvenv、システムライブラリの依存関係。これらがホスト側のほかのプロセスと衝突した時の復旧コストが高すぎるんです。

Dockerで運用するメリットは大きく4つあります。

  • 再現性: 同じイメージを別サーバーに持っていけば同じ環境が立ち上がる
  • 隔離: ホストOSや他サービスから完全に分離。Hermes Agentが暴走してもホストに影響しない
  • デプロイ容易性: docker compose up -d だけで起動・停止・更新が完結
  • セキュリティ監査対応: Issue #7826で議論されているような任意コマンド実行リスクを、コンテナ境界で物理的に閉じ込められる

特に最後の点が重要で、セキュリティ面の前提についてはHermes Agent セキュリティ監査 Issue #7826 で議論された任意コマンド実行リスクで詳しく書きました。Docker化は、その対策の中でも最もコスパが良い一手です。

最小構成: docker run ワンライナーから始める

まずは動かしてみる、というフェーズなら以下のワンライナーで十分です。公式ドキュメント(hermes-agent.nousresearch.com/docs/user-guide/docker)に近い形ですが、後述する地雷を避けるための最小限の修正を加えています。

docker run -d \
  --name hermes \
  -e HERMES_API_KEY=$HERMES_API_KEY \
  -e HERMES_WRITE_SAFE_ROOT=/data \
  -v hermes_data:/data \
  -p 8080:8080 \
  --restart unless-stopped \
  nousresearch/hermes-agent:latest

ポイントは -v hermes_data:/data でnamed volumeを必ず割り当てること。これを忘れると、コンテナを再起動した瞬間に学習した記憶がすべて消えます。

永続ボリューム設計: Issue #5563の罠を踏まない

GitHub Issue #5563は、Hermes Agentコミュニティで最も「踏んだ人が多い」事故です。永続ボリュームをマウントせずにコンテナを再起動すると、MEMORY.mdとstate.dbが消失し、Hermesが「初めまして」状態に戻るという問題です。

Hermes Agentが状態を保持する場所は主に3つあります。

  • /data/state.db: タスク状態・実行履歴のSQLite DB
  • /data/memory.md: 長期記憶(ユーザー指示・学習内容)
  • /data/skills/: 動的にインストールされたスキル群

これらが格納される /data ディレクトリ全体をvolumeに切り出すのが鉄則です。私たちの本番構成では、named volumeではなくbind mountを使い、ホスト側のバックアップ対象パスに揃えています。

volumes:
  - /srv/hermes/data:/data
  - /srv/hermes/logs:/var/log/hermes

こうしておくと、ホスト側で resticrsync を回すだけで丸ごとバックアップできます。

HERMES_UIDパーミッション問題(Issue #23402)

もう一つの定番トラブルが、Issue #23402で報告されているパーミッション問題です。コンテナ内のHermesプロセスが uid=1000 で動いている一方、ホスト側でマウントしたディレクトリの所有者が違うuidになっていると、書き込み時に Permission denied が出ます。

このIssueは執筆時点でまだ未解決で、コミュニティから要望が多い項目です。回避策としては、ビルド時または起動時にUIDを揃える方法が確実です。

# Dockerfile での解決例
ARG HERMES_UID=1000
ARG HERMES_GID=1000
RUN groupadd -g ${HERMES_GID} hermes \
  && useradd -u ${HERMES_UID} -g ${HERMES_GID} -m hermes
USER hermes

そしてホスト側で:

sudo mkdir -p /srv/hermes/data
sudo chown -R 1000:1000 /srv/hermes

docker-compose側でビルド引数を渡すなら:

services:
  hermes:
    build:
      context: .
      args:
        HERMES_UID: 1000
        HERMES_GID: 1000

「とりあえず動かしたい」段階で chmod 777 を当ててしまう人がいますが、本番ではほぼ間違いなくセキュリティ監査で引っかかります。最初からUIDを合わせる設計にしておく方が結果的に楽です。

s6-overlay で複数プロセスを1コンテナ内に

Hermes Agentを実運用すると、本体だけでは完結しないシーンが出てきます。たとえば外部からのWebhookを受けるgatewayプロセス、定期実行のcron、ログ転送のagent。これらを別コンテナで分けるか、1コンテナにまとめるかという設計判断が発生します。

私たちは「論理的に同一の責務であれば1コンテナにまとめる」方針で、その時に使うのがs6-overlayです。コンテナのPID 1問題を解決しつつ、複数プロセスを正しく監視・再起動してくれる軽量スーパーバイザーです。

ディレクトリ構成は以下のようになります。

/etc/s6-overlay/s6-rc.d/
├── hermes/
│   ├── type        # "longrun"
│   ├── run         # 起動スクリプト
│   └── dependencies.d/base
├── gateway/
│   ├── type
│   ├── run
│   └── dependencies.d/base
└── user/contents.d/
    ├── hermes
    └── gateway

Dockerfileの末尾はこうなります。

ARG S6_OVERLAY_VERSION=3.2.0.0
ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz
ENTRYPOINT ["/init"]

1プロセスがクラッシュしても他に影響せず、s6が自動で再起動します。Hermes本体がOOMで落ちた時にgatewayまで巻き込まれるという最悪のケースを避けられます。

本番想定の docker-compose.yml 全体像

docker-compose 3コンテナ構成図(Hermes本体 + Postgres + Caddyの役割と接続関係)

ここまでの要素を全部入れた、私たちが実案件で使っているdocker-compose.ymlのテンプレートです。Hermes本体 + Postgres(記憶の冗長保管) + Caddy(自動TLSリバースプロキシ)の3コンテナ構成。

services:
  hermes:
    image: nousresearch/hermes-agent:latest
    container_name: hermes
    restart: unless-stopped
    user: "1000:1000"
    environment:
      HERMES_API_KEY: ${HERMES_API_KEY}
      HERMES_WRITE_SAFE_ROOT: /data
      HERMES_DB_URL: postgres://hermes:${PG_PASSWORD}@postgres:5432/hermes
      ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
    volumes:
      - /srv/hermes/data:/data
      - /srv/hermes/logs:/var/log/hermes
    networks:
      - hermes_internal
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETUID
      - SETGID
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/healthz"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 60s
    depends_on:
      postgres:
        condition: service_healthy

  postgres:
    image: postgres:16-alpine
    container_name: hermes-postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: hermes
      POSTGRES_PASSWORD: ${PG_PASSWORD}
      POSTGRES_DB: hermes
    volumes:
      - /srv/hermes/postgres:/var/lib/postgresql/data
    networks:
      - hermes_internal
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U hermes"]
      interval: 10s

  caddy:
    image: caddy:2-alpine
    container_name: hermes-caddy
    restart: unless-stopped
    ports:
      - "443:443"
      - "80:80"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - /srv/hermes/caddy:/data
    networks:
      - hermes_internal
    depends_on:
      - hermes

networks:
  hermes_internal:
    driver: bridge

Caddyfileの中身はこれだけで自動TLS化されます。

hermes.example.com {
  reverse_proxy hermes:8080
}

セキュリティ強化のポイント

本番運用のセキュリティ4設定チェックリスト(非root実行・cap_drop・no-new-privileges・内部ネットワーク隔離)

本番運用ではセキュリティ設定を「デフォルトに任せない」ことが大切です。compose内で抑えているのは以下4点です。

  • 非root実行: user: "1000:1000" で必ず指定
  • capability drop: cap_drop: [ALL] でフルにドロップしてから必要なものだけ cap_add
  • no-new-privileges: setuid系のバイナリで権限昇格できないようにする
  • ネットワーク隔離: hermes_internal という内部ネットワークだけで通信し、外部公開はCaddy経由のみ

「常にオンラインで動かしておきたいけどクラウド代は抑えたい」というニーズなら、家庭内に小さなマシンを置く構成も現実的です。コストとパフォーマンスのリアルな数字はMac mini でHermes Agentを常駐運用する場合の月額コスト試算【2026年版】にまとめています。

ヘルスチェックとバックアップ戦略

本番運用で軽視されがちなのが、コンテナのヘルスチェックです。Hermes Agentは外部APIへの長時間リクエストを抱える性質上、「プロセスは生きているがリクエストを受け付けない」状態に陥りやすい。HEALTHCHECK を入れておけば、Docker側で自動的に異常を検知して restart ポリシーが発火します。

バックアップは /srv/hermes/data/srv/hermes/postgres の2か所が対象。私たちはresticでローカルNAS + S3互換ストレージへ二重に取って、世代管理は7日 / 4週 / 12か月のルールで運用しています。MEMORY.mdが壊れた時に「3日前の自分」へ戻せる安心感は思っているより大きいです。

Claude Codeからの移行を考えている方へ

すでにClaude Codeで日常業務を回している方が、Hermes Agentへの移行を検討する際にも、このDocker隔離は重要なステップになります。Claude Code から Hermes Agent への段階的移行ガイドでは、いきなり本番ホストにインストールするのではなく「ステップ4でDocker環境に隔離してから本番化する」フローを推奨しています。本記事のcompose定義はそのまま流用できます。

まとめ

Hermes AgentをDockerで本番運用する場合、押さえるべきは次の6点です。

  • 永続ボリューム(/data)は必ずマウント。Issue #5563の再発防止
  • HERMES_UIDをDockerfileで明示し、ホスト側ファイル所有者と揃える
  • s6-overlayでHermes本体・gateway・cronを1コンテナ内に同居させつつ独立監視
  • compose構成はHermes + Postgres + Caddyの3コンテナで自動TLSまで完結
  • 非root・cap_drop・no-new-privileges・内部ネットワーク隔離をデフォルトで適用
  • ヘルスチェック + restic等で「3日前に戻せる」バックアップ運用を回す

Hermes Agentは「動かす」より「動かし続ける」フェーズで急に難易度が上がるツールです。最初の構築段階で本記事の構成にしておけば、半年後に「Permission denied連発で土日が潰れる」事態は避けられます。私たちは介護・建設業界のクライアント環境でこの構成を回していますが、日々の運用負荷はほぼゼロです。

本番投入を検討されている方の参考になれば幸いです。

[ FREE DISCOVERY ]

Hermes Agent を本気で活用するなら

「Hermes Agent を自分で使いこなしたい」「自社の業務に組み込みたい」
— そんな方は、まず初回無料相談でお話ししてみませんか。

個人・副業の方お悩み相談・レクチャー・伴走無料相談を予約 →法人・経営者の方導入・運用・開発サポート無料相談を予約 →
← 記事一覧に戻る