Skip to main content

Logs

Everything the instance does goes to its container logs. There is no log file to find; docker compose logs reads them.

Per service

The stack runs a handful of containers. Name one to see just its output:

docker compose logs api # the API: requests, boot sequence, migrations, errors
docker compose logs web # the web server fronting the built interface
docker compose logs db # Postgres
docker compose logs caddy # TLS: certificate issuance and renewal

Useful flags:

  • --tail=100 shows the last 100 lines instead of the whole history.
  • -f follows live, so you can watch a boot or reproduce a problem in real time.
  • --since=10m limits to the last ten minutes.
docker compose logs -f --tail=50 api

What to look for

  • A boot that failed. In api, the startup sequence logs each step. A failed database migration stops the boot and names the migration in the line before the crash. This is the signal behind a container stuck in restarting or unhealthy; see Health and status.
  • Request errors. The api logs each HTTP request. A run of 500s clustered around one action points at where to look; a wall of 403s is usually a permission or workspace-scope issue rather than a crash.
  • Certificates. If HTTPS is not working, caddy is where the reason is: a wrong DNS-provider token, a blank ACME email, or no outbound internet on the box. Operating walks through the common cases.
  • Database. db shows Postgres itself. Connection refused here early in a boot usually means the api started before the database was ready, which the healthcheck dependency normally prevents; a persistent failure is worth a closer look.

Narrowing down

docker compose logs is plain text, so a pipe does the filtering:

docker compose logs --tail=500 api | grep -i error
docker compose logs api | grep -i migrat

For a live problem, follow the api while you reproduce it (docker compose logs -f api) and act in the app: the request that fails shows up as it happens, which beats reading history after the fact.