From 6ed9dc39e8d7c708a3d3e2ae25a527a5012d2bfe Mon Sep 17 00:00:00 2001 From: dtoro Date: Tue, 28 Jul 2026 20:08:35 +0200 Subject: [PATCH] fix(compose): wait for the API to be healthy before starting nomos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nomos declared `depends_on: api: condition: service_started`, which only waits for the container to exist. It came up while the API was still binding :8090, failed its MCP initialize with "connection refused", exited 1, and crash-looped for ~25 seconds on every single deploy. It always recovered on its own, which is precisely why it went unnoticed. service_healthy waits for the API to answer, so this needs api to declare a healthcheck — wget is BusyBox's, already present in the alpine runtime image, so nothing new is installed. /healthz pings the database, so "healthy" means genuinely able to serve rather than merely listening. Co-Authored-By: Claude --- docker-compose.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 55ca1b5..b084ce1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -83,6 +83,18 @@ services: command: ["api"] stop_signal: SIGTERM stop_grace_period: 30s + # Exists so nomos can wait for the API to actually answer rather than just + # for its container to exist — see nomos's depends_on below. wget is + # BusyBox's, already in the alpine runtime image, so this adds no + # dependency. /healthz pings the DB, so "healthy" means genuinely ready. + healthcheck: + test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:8090/healthz"] + interval: 5s + timeout: 3s + retries: 10 + # Migrations and seed run before this container, but the first bind can + # still take a moment; failures inside the start period don't count. + start_period: 10s # Scheduler (Phase 3) — observe loop scheduler: @@ -139,7 +151,12 @@ services: profiles: ["full"] depends_on: api: - condition: service_started + # service_started only waits for the container to exist, so nomos came + # up while the API was still binding :8090, failed its MCP initialize, + # exited 1, and crash-looped for ~25s on every single deploy. It always + # recovered, which is exactly why it went unnoticed. service_healthy + # waits for the API to actually answer. + condition: service_healthy environment: NOMOS_MCP_URL: http://api:8090/mcp NOMOS_AGENT_SLUG: agent:nomos