侧边栏壁纸
  • 累计撰写 109 篇文章
  • 累计创建 54 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

docker hermes opencode ollama

FlyingEagle
2026-07-23 / 0 评论 / 0 点赞 / 16 阅读 / 7,463 字

hermes-opencode

Docker image that bakes OpenCode CLI into the Hermes Agent container. One container, free AI models, zero SSH tunnels. Extensible recipe for any Debian-based tool you want to bake in.


What’s Included

Component Version Location
Hermes Agent latest Base image (Nous Research)
OpenCode CLI 1.18.4 /usr/local/bin/opencode
Debian OS 13 (Trixie) Base image OS
SearXNG latest Optional (separate container)
Ollama latest Optional (separate container, local vision models)

Architecture

Layer Stack (how the image is built)

Layer 0: FROM nousresearch/hermes-agent:latest
         └── Debian 13 + Python + Hermes Agent binaries

Layer 1: RUN apt-get install ... (Debian packages)
         └── vim, htop, build-essential, python3-pip, git, curl, ...

Layer 2: RUN curl ... | tar -xzf ... (binaries)
         └── OpenCode CLI binary

         = hermes-opencode:latest  (built image)
                  ↓
         docker compose up -d
                  ↓
Layer 3: Container runtime (bind mounts, env vars)

         = Running container

Each RUN in the Dockerfile creates a layer. Docker caches layers — rebuild is fast if only bottom layers change.

Container Network

┌─────────────────────────────────────────────────────┐
│              hermes-opencode_hermes-net               │
│                                                      │
│  ┌──────────────────┐     ┌──────────────────┐     │
│  │ hermes-opencode  │     │     searxng      │     │
│  │ (Hermes+OpenCode)│     │   (metasearch)   │     │
│  │                 │     │                  │     │
│  │ /usr/local/bin/ │     │   port 8080      │     │
│  │ opencode        │     │                  │     │
│  └────────┬────────┘     └──────────────────┘     │
│           │                                           │
│  ┌────────┴────────┐                                 │
│  │     ollama      │                                 │
│  │ (local LLM/VLM)│                                 │
│  │ port 11434     │                                 │
│  └────────────────┘                                 │
└─────────────────────────────────────────────────────┘

Quick Start

# Fresh deploy (from ext_storage)
rsync -avP /ext_storage/hermes-opencode/ root@YOUR_VPS:/opt/hermes-opencode/
cd /opt/hermes-opencode
mkdir -p workspace searxng && chown -R 10000:10000 workspace searxng
docker compose up -d

# Or use the deploy script
bash /ext_storage/hermes-opencode/deploy.sh <VPS_IP>

Verify

docker exec hermes-opencode-hermes-opencode-1 hermes --version
docker exec hermes-opencode-hermes-opencode-1 opencode --version
# → 1.18.4

Persistence Architecture

This deployment uses bind mounts — data lives directly on the host filesystem and is accessible from both the container and the host.

Bind Mount: ./hermes_data    → /opt/data         (Hermes config, memory, skills, profiles)
Bind Mount: ./opencode_data  → /home/hermes/.opencode  (OpenCode sessions)
Bind Mount: ./workspace      → /home/hermes/workspace  (working files, host-accessible)
Volume Type Persists across restart? Host-accessible?
./hermes_data Bind mount ✅ Yes ✅ Yes — direct file access
./opencode_data Bind mount ✅ Yes ✅ Yes — direct file access
./workspace Bind mount ✅ Yes ✅ Yes — direct file access
./searxng Bind mount ✅ Yes ✅ Yes — direct file access

Why bind mounts instead of named volumes?

Factor Named Volumes Bind Mounts
Host file access ❌ Via docker volume commands ✅ Direct file access
Backup docker volume cp cp / rsync directly
Root required No Yes
NFS/storage integration Limited ✅ Works with NFS
Chown permissions Docker-managed Manual

Named volumes are better when:

  • Running as a non-root user
  • Need portability across different host environments
  • Want protection from accidental host directory deletion

Bind mounts are better when:

  • Running as root (you have full control)
  • Need direct file access from host (backup, edit, inspect)
  • Using NFS or other network storage
  • Want simple backup with standard tools

This deployment uses bind mounts because it runs as root with NFS backup storage.


Ollama Integration (Image Recognition)

Hermes can use Ollama for local image recognition via HTTP API:

Python (in Hermes)  →  Ollama API (172.18.0.x:11434)  →  gemma4:31b-cloud

Example usage:

import urllib.request, json, base64

with open('/path/to/image.jpg', 'rb') as f:
    img_b64 = base64.b64encode(f.read()).decode()

payload = json.dumps({
    'model': 'gemma4:31b-cloud',
    'prompt': '描述这张图片',
    'images': [img_b64],
    'stream': False
}).encode()

req = urllib.request.Request(
    'http://172.18.0.4:11434/api/generate',
    data=payload,
    headers={'Content-Type': 'application/json'},
    method='POST'
)
with urllib.request.urlopen(req, timeout=120) as resp:
    result = json.loads(resp.read().decode())
    print(result['response'])

GPU Passthrough

GPU access is runtime-only — the Dockerfile doesn’t handle GPU. It’s purely controlled by the compose file and host driver.

HOST machine                          Container
(nvidia-driver installed)              (nvidia runtime)

Physical GPU (PCIe)  ←── nvidia driver ──→ /dev/nvidia0, /dev/nvidiactl
                                                   ↓
                                           container sees GPU

Host-level setup (do once on host)

# 1. Install NVIDIA driver
apt-get update && apt-get install -y nvidia-driver-545 nvidia-smi

# 2. Install nvidia-container-toolkit
distribution=bookworm
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
    sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
    tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
apt-get update && apt-get install -y nvidia-container-toolkit

# 3. Configure Docker to use nvidia runtime
nvidia-ctk runtime configure --runtime=docker
systemctl restart docker

Compose GPU config

services:
  hermes-opencode:
    runtime: nvidia            # ← maps GPU devices into container
    environment:
      - NVIDIA_VISIBLE_DEVICES=all

Container-side GPU tools (add to Dockerfile)

RUN apt-get update && apt-get install -y --no-install-recommends \
    nvtop \
    nvidia-smi \
    && rm -rf /var/lib/apt/lists/*

Extending the Recipe (baking more tools)

The Dockerfile is a recipe. Add whatever Debian packages or binaries you need.

Add Debian packages

# In Dockerfile, add to the RUN apt-get ... line
RUN apt-get update && apt-get install -y --no-install-recommends \
    tree \
    neofetch \
    jq \
    unzip \
    zip \
    && rm -rf /var/lib/apt/lists/*

Add Ollama (for local LLM inference)

# Download latest ollama binary (Debian apt package is outdated)
RUN curl -sL https://ollama.ai/install.sh | sh

# Or pin to specific version
RUN curl -sL https://ollama.ai/install.sh | sh OLLAMA_VERSION=0.5.4

Add any binary

# Download pre-built binary and install to /usr/local/bin
RUN curl -sL "https://github.com/some/tool/releases/download/v1.0/tool-linux-amd64.tar.gz" | \
    tar -xzf - -C /usr/local/bin && \
    chmod 755 /usr/local/bin/tool

Rebuild after editing

cd /opt/hermes-opencode
docker compose build
docker compose up -d

Deploy Scripts

Fresh deploy (new VPS)

# From this machine:
bash /ext_storage/hermes-opencode/deploy.sh <VPS_IP>

# What it does:
#   1. rsync files to VPS
#   2. Create workspace/searxng directories
#   3. Generate SearXNG secret_key
#   4. Build Docker image
#   5. Start containers
#   6. Test persistence (docker restart + verify)

Volumes

Volume Mount Point What lives here
./hermes_data /opt/data Hermes config, memory, skills, profiles
./opencode_data /home/hermes/.opencode OpenCode sessions, cache
./workspace /home/hermes/workspace Working files (host-accessible)
./searxng /etc/searxng SearXNG settings

Environment Variables

Variable Default Description
HERMES_REAL_HOME /opt/data Redirects Hermes config to bind mount
OPENCODE_API_KEY Optional API key for paid OpenCode models

File Structure

hermes-opencode/
├── Dockerfile                     # Image recipe (base + packages + binaries)
├── docker-compose.yml            # Containers + volumes + networks
├── deploy.sh                     # Fresh deploy to new VPS
├── README.md                     # This file
├── build.sh                      # Legacy build script
├── searxng/
│   └── settings.yml             # SearXNG config (secret_key generated at deploy)
└── workspace/                    # Working files (created at deploy)

Troubleshooting

Container exits immediately

docker logs hermes-opencode-hermes-opencode-1

OpenCode not found

docker exec hermes-opencode-hermes-opencode-1 which opencode
# → /usr/local/bin/opencode

Permission denied (workspace files)

sudo chown -R 10000:10000 /opt/hermes-opencode/workspace

Ollama not accessible from Hermes

# Check Ollama container IP
docker inspect ollama --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'

# Verify both containers on same network
docker network inspect hermes-opencode_hermes-net

Network issues (SearXNG)

# Ensure both containers on same hermes-net
docker network inspect hermes-opencode_hermes-net

Credits

0

评论区