chore(docker-dev): readiness-gated deploy.sh + Traefik access log for the first-POST 404

This commit is contained in:
Joseph Doherty
2026-08-17 05:32:44 -04:00
parent 1edfc263ec
commit a61b3c98a2
3 changed files with 123 additions and 2 deletions
+25 -2
View File
@@ -86,10 +86,33 @@ Central nodes authenticate against the shared GLAuth at `10.100.0.35:3893` (base
## Headless deploy
```bash
POST http://localhost:9200/api/deployments
X-Api-Key: docker-dev-deploy-key
./docker-dev/deploy.sh # trigger a deploy (no request body)
./docker-dev/deploy.sh artifact.json # …sending that JSON file as the request body
```
`deploy.sh` polls `http://localhost:9200/health/ready` (every 2 s, up to 120 s) and only then
issues the single, un-retried `POST http://localhost:9200/api/deployments` with
`X-Api-Key: docker-dev-deploy-key`. Override the URL / key / timeout via `OTOPCUA_ADMIN_URL`,
`OTOPCUA_DEPLOY_API_KEY`, `OTOPCUA_READY_TIMEOUT_SECONDS`.
### First-POST 404
The first headless POST after `up -d` was seen answering **404** ~40 s into boot (2026-08-17 live
gate), clearing on retry. Neither end can produce it: the AdminUI maps every route synchronously
before `RunAsync` (`Program.cs:740` maps the deploy API, `:803` runs) and that endpoint's only
failure modes are 503 / 401 / 422 / 409 / 500 — it has no 404 path; and Traefik answers a *matched*
router whose servers are all down with **503 "no available server"** (the checked-in
`traefik-dynamic.yml` router is `PathPrefix(/)` → `otopcua-admin` with a `/health/active`
healthCheck). Traefik's `api@internal` router (`PathPrefix(/api)`) is bound to the `:8080`
entrypoint (host 8089), not `web`/`:9200`, so it does not shadow `/api/deployments` either. So a
404 from `:9200` is Go's default "404 page not found" — **no router matched at that instant**;
the mechanism is unconfirmed. The `--accesslog=true --accesslog.fields.defaultmode=keep` flags on
the `traefik` service exist to diagnose the next occurrence: `docker compose -f
docker-dev/docker-compose.yml logs traefik` and look for the request with an empty `RouterName`.
The readiness gate in `deploy.sh` avoids the race (a 200 through `:9200` proves both a matched
router and a live backend), so a 404 *after* the gate is new evidence and the script fails loudly
saying so.
## Tear down
```bash