Torna al blog
HermesDockerTroubleshootingSelf-Hosting

Il container Docker di Hermes Agent continua a riavviarsi

Diagnostica perché il container Docker di Hermes Agent continua a riavviarsi: OOM, .env sbagliato, permessi volume, porte e mismatch ARM.

Di Hermify Team||7 min di lettura
Terminale scuro che mostra un container Docker di Hermes Agent in loop di restart, con l'exit code evidenziato in verde

Il tuo container Hermes Agent parte, muore dopo pochi secondi e Docker lo rialza. docker ps mostra una riga tipo Restarting (137) 3 seconds ago, il bot non risponde su Telegram e hermes logs scorre lo stesso banner di avvio all'infinito. Quel loop è quasi sempre uno di cinque problemi molto specifici, e l'exit code stampato da Docker ti dice quale. Questo post li affronta nell'ordine che sistema più agenti.

Se non hai mai fatto girare il container, parti da come far girare Hermes Agent in Docker. Questa guida presume che l'immagine si scarichi bene, che il compose sia al suo posto e che qualcosa si rompa nel momento in cui il processo parte.

Passo 1 - Leggi l'exit code vero prima di toccare qualsiasi cosa

Docker espone l'exit code dell'ultima esecuzione dentro lo stato del container. Leggilo direttamente invece di indovinare dai log:

docker inspect --format='{{.State.ExitCode}} OOM={{.State.OOMKilled}} err={{.State.Error}}' hermes-agent

Quella singola riga ti dà tre cose insieme: l'exit code, se il processo è stato ucciso dall'OOM killer del kernel e qualsiasi errore a livello di daemon che Docker ha attaccato al run. L'exit code restringe tantissimo la ricerca:

  • 137 - al processo è stato mandato SIGKILL. Quasi sempre un OOM kill dovuto a un limite di memoria del container o all'host senza RAM, ogni tanto un docker stop che ha sforato i 10 secondi di grazia.
  • 139 - segmentation fault. Su Hermes Agent salta fuori quando l'architettura dell'immagine non corrisponde all'host (immagine amd64 su un VPS ARM, o viceversa).
  • 125 / 126 / 127 - è Docker stesso che non è riuscito a far partire il container. 125 vuol dire che il daemon ha rifiutato il run (opzioni sbagliate, immagine mancante). 126, che l'entrypoint esiste ma non è eseguibile. 127, che il path dell'entrypoint è sbagliato o manca la shell che gli serve.
  • 1 o 2 - il processo di Hermes Agent è arrivato ad avviarsi, ha fatto la sua validazione e si è chiuso con un errore applicativo. Lancia docker logs hermes-agent --tail 100 e cerca la prima riga che non appartiene al banner di avvio.

Solo quando sai in quale di questi casi sei ha senso mettere mano alla configurazione. Alzare la memoria a caso o riscrivere il compose di solito nasconde la causa vera e produce un container che cade una settimana dopo per lo stesso motivo.

Terminale con l'output di docker inspect e exit code, flag OOMKilled e campo error evidenziati

Passo 2 - Exit 137 con OOMKilled=true: la trappola del VPS da 1 GB

Di gran lunga la causa più comune su Hermes Agent, e quella contro cui mette in guardia la guida su VPS economici per agenti IA. L'agente a riposo non è pesante, ma appena gli mandi una conversazione lunga, un messaggio vocale o una chiamata di tool MCP la memoria sale in fretta. Su un VPS da 1 GB senza swap, l'OOM killer del kernel sceglie il processo più grande (il gateway) e lo termina. La restart policy di Docker fa partire subito un nuovo container, che alloca memoria allo stesso modo e viene ucciso allo stesso modo. Quello è il tuo loop.

Conferma nel log del kernel:

sudo dmesg -T | grep -i -E 'oom-kill|killed process' | tail -5
# oppure su host systemd:
sudo journalctl -k --since '30 minutes ago' | grep -i oom

Vedrai una riga con il processo principale del container (hermes o node) e il suo RSS nel momento del kill. Due fix, in ordine di preferenza:

  1. Dai più RAM all'host. Sotto i 2 GB Hermes Agent continuerà a sbattere contro questo tetto ogni volta che una conversazione si allunga o parte la modalità vocale. Il pavimento realistico per un agente comodo a singolo utente è 2 GB con swap attiva o 4 GB senza.
  2. Aggiungi swap sull'host. Su un VPS Linux: sudo fallocate -l 2G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile, poi persistila in /etc/fstab. Lo swap è più lento della RAM, ma è la differenza tra un container ucciso e una risposta lenta.

Se hai messo un mem_limit esplicito nel compose, controllalo anche lui. Un limite sotto 1 GB riproduce lo stesso OOM anche su un host grosso. Rimuovilo o portalo ad almeno 1,5 GB prima di riavviare.

Passo 3 - Exit 1 o 2 con un errore di config nei log

Se l'exit code è 1 o 2, Hermes Agent è arrivato ad avviarsi abbastanza da eseguire la sua validazione e ha rifiutato la configurazione. I log ti dicono cosa. Tre forme coprono la maggior parte:

  • .env mancante o mal fatto. Il gateway non parte senza una chiave provider valida. Cerca Provider key not set o Missing TELEGRAM_BOT_TOKEN nei log. Controlla che il .env non abbia virgolette di troppo attorno ai valori (OPENROUTER_API_KEY="sk-..." va bene, OPENROUTER_API_KEY = "sk-..." con spazi no) né a capo Windows (file .env dovrebbe dire ASCII text, non CRLF).
  • Directory dati non scrivibile. Se vedi EACCES: permission denied, open '/data/config.json', il container gira come utente non root e la directory bind-mount dell'host appartiene a qualcun altro. Sull'host: sudo chown -R 1000:1000 ~/.hermes/data. L'UID 1000 è quello che usa l'immagine; non far girare il container come root solo per aggirare questa cosa.
  • Porta già occupata. bind: address already in use vuol dire che sull'host un altro processo tiene già la porta 8642. Trovalo con sudo lsof -i :8642 e fermalo, oppure mappa Hermes Agent su un'altra porta host nel compose (ports: - "9642:8642").

Nessuno di questi si risolve da solo con i restart. Sistema la configurazione e rifai docker compose up -d.

Passo 4 - Exit 139 o "exec format error": la trappola dell'immagine ARM

Se il container muore in millisecondi con codice 139, o Docker registra exec /usr/bin/node: exec format error, l'immagine scaricata non corrisponde alla CPU dell'host. Succede tipicamente su Oracle Cloud Ampere, AWS Graviton o Raspberry Pi, tutti ARM64. Se hai preso un'immagine costruita solo per linux/amd64, il kernel non riesce a eseguire il binario e Docker continua a provare.

Confronta le architetture di host e immagine:

uname -m                                   # aarch64 = ARM64, x86_64 = amd64
docker inspect hermes-agent-image \
  --format='{{.Architecture}}/{{.Os}}'     # dovrebbe combaciare con uname -m

Se non combaciano, scarica specificando la piattaforma. L'immagine ufficiale di Hermes Agent è multi-arch, quindi basta indicarla:

docker pull --platform linux/arm64 hermes/agent:latest

Se costruisci un'immagine tua, ricostruiscila con docker buildx build --platform linux/arm64,linux/amd64 e pusha entrambi i tag. Far girare un'immagine ARM su un host amd64 è lo stesso bug allo specchio e produce lo stesso 139.

Passo 5 - La restart policy sta nascondendo l'errore vero

restart: always è il default giusto per un agente in produzione, ma in debug trasforma ogni fallimento di avvio in un loop stretto che riempie i log e nasconde il primo errore vero. Quando qualcosa non va, passa a una policy che esponga il fallimento:

services:
  hermes-agent:
    image: hermes/agent:latest
    restart: "on-failure:3"

on-failure:3 riparte fino a 3 volte su uscite diverse da zero e poi si ferma. Il container resta fermo con il fallimento visibile in docker ps -a, e i log non vengono sovrascritti dai nuovi boot. Una volta risolta la causa, torna a restart: always o unless-stopped. La guida al debugging e observability di Hermes Agent copre la rotazione dei log che tiene tutto questo leggibile in produzione.

Frammento di docker-compose.yml con la restart policy evidenziata, di fianco a un output di docker ps che mostra il container fermo

Quando il fix non vale il weekend

Tutti i fallimenti qui sopra si sistemano, ma ognuno costa una domenica pomeriggio a leggere log del kernel e riscrivere compose. Se sei arrivato qui perché il bot è giù da tre giorni e vuoi solo tornare a usare l'agente, la versione gestita esiste esattamente per questo. Hermify fa girare Hermes Agent al posto tuo su Telegram, con il volume di memoria, le chiavi provider e la restart policy già collegate, così un container che cade non è più un problema tuo da diagnosticare. Inizia con Hermify e torna online in circa un minuto.

Per chi preferisce continuare a self-hostare, il prossimo post da leggere è Hermes Agent memoria e skill - il secondo motivo più comune per cui un agente dockerizzato sembra rotto.

Sources

Avvia il tuo Hermes Agent

Porta la tua chiave API, collega Telegram e ottieni un agente IA che migliora da solo, online in 60 secondi.

Inizia ora