Docker: the compose files set no log size limit, and the healthcheck adds an access line every 30 seconds #1126

Open
opened 2026-10-31 03:04:12 +00:00 by tiagoagueda · 0 comments
Owner

What exists today

None of docker/compose.yml, compose.postgres.yml, compose.build.yml, compose.postgres.build.yml or compose.hardened.yml has a logging: key (grep for logging: and max-size finds nothing). Docker's default json-file driver keeps every line for the life of the container unless the host's daemon.json sets log-opts; most hosts do not. The wiki's installation pages do not mention it either (grep of postulo.wiki for max-size and logging: finds nothing relevant).

docker/Dockerfile:360-361 runs curl -fsS http://127.0.0.1:8000/healthz every 30 s, and the gunicorn command (lines 391-394) writes every request to the access log with --access-logfile -, so the container log gets one GET /healthz line every 30 s, 2,880 a day, for as long as the container runs. The worker and scheduler override the healthcheck with a find on their heartbeat files (compose.yml:69, :111), so this is the web container only. The larger stream is the worker's (B1).

What would change

  1. In each runnable compose file, one YAML anchor applied to every service:
    x-logging: &logging
      driver: local
      options:
        max-size: "10m"
        max-file: "3"
    
    and logging: *logging on postulo, scheduler, worker (and db in the PostgreSQL file). Docker's local driver is the one Docker's own documentation recommends (compressed, rotated by default); json-file with max-size/max-file is the alternative if an operator's collector reads the JSON files. docker logs works with both.
  2. Leave /healthz out of the access log: in config/gunicorn_logging.py's RedactingLogger, override access() to return early for a GET /healthz answered 200 from loopback. A failing healthcheck (any other status) is still logged. gunicorn has no option for this, so the logger class already in place is the hook.
  3. A line in the wiki's Docker installation page saying the files cap logs at 30 MB per container and how to change it.

What it saves or protects

medium: container logs on the host stop growing without bound (the idle worker alone writes about 86,400 lines a day today, see B1; the healthcheck 2,880 access lines a day on the web container)

Accessibility

none

Decided by the maintainer (2026-10-31)

compose: log driver local 10 MB x 3 in one shared anchor; successful /healthz left out of the access log

Decisions

  • Set the log driver in the shipped compose files? Recommended: yes, with local and 10 MB × 3; an operator with a central collector changes one anchor.
  • Drop successful healthcheck lines from the access log? Recommended: yes; a failure is still logged, and Docker records health results itself (docker inspect).
  • Split? Recommended: one issue; split into: compose logging limits (1, 3) and the healthcheck access line (2) only if the user wants the compose change decided separately.

Found by the efficiency and reliability audit of 2026-10-30 (finding D6; index postulo/postulo#1108). Checked against main at daee30b15 (2026-10-30).

## What exists today None of `docker/compose.yml`, `compose.postgres.yml`, `compose.build.yml`, `compose.postgres.build.yml` or `compose.hardened.yml` has a `logging:` key (grep for `logging:` and `max-size` finds nothing). Docker's default `json-file` driver keeps every line for the life of the container unless the host's `daemon.json` sets `log-opts`; most hosts do not. The wiki's installation pages do not mention it either (grep of `postulo.wiki` for `max-size` and `logging:` finds nothing relevant). `docker/Dockerfile:360-361` runs `curl -fsS http://127.0.0.1:8000/healthz` every 30 s, and the gunicorn command (lines 391-394) writes every request to the access log with `--access-logfile -`, so the container log gets one `GET /healthz` line every 30 s, 2,880 a day, for as long as the container runs. The worker and scheduler override the healthcheck with a `find` on their heartbeat files (`compose.yml:69`, `:111`), so this is the web container only. The larger stream is the worker's (B1). ## What would change 1. In each runnable compose file, one YAML anchor applied to every service: ```yaml x-logging: &logging driver: local options: max-size: "10m" max-file: "3" ``` and `logging: *logging` on `postulo`, `scheduler`, `worker` (and `db` in the PostgreSQL file). Docker's `local` driver is the one Docker's own documentation recommends (compressed, rotated by default); `json-file` with `max-size`/`max-file` is the alternative if an operator's collector reads the JSON files. `docker logs` works with both. 2. Leave `/healthz` out of the access log: in `config/gunicorn_logging.py`'s `RedactingLogger`, override `access()` to return early for a `GET /healthz` answered 200 from loopback. A failing healthcheck (any other status) is still logged. gunicorn has no option for this, so the logger class already in place is the hook. 3. A line in the wiki's Docker installation page saying the files cap logs at 30 MB per container and how to change it. ## What it saves or protects medium: container logs on the host stop growing without bound (the idle worker alone writes about 86,400 lines a day today, see B1; the healthcheck 2,880 access lines a day on the web container) ## Accessibility none ## Decided by the maintainer (2026-10-31) compose: log driver local 10 MB x 3 in one shared anchor; successful /healthz left out of the access log ## Decisions - **Set the log driver in the shipped compose files?** Recommended: yes, with `local` and 10 MB × 3; an operator with a central collector changes one anchor. - **Drop successful healthcheck lines from the access log?** Recommended: yes; a failure is still logged, and Docker records health results itself (`docker inspect`). - **Split?** Recommended: one issue; split into: compose logging limits (1, 3) and the healthcheck access line (2) only if the user wants the compose change decided separately. --- Found by the efficiency and reliability audit of 2026-10-30 (finding D6; index postulo/postulo#1108). Checked against `main` at `daee30b15` (2026-10-30).
tiagoagueda added this to the 1.0.0 milestone 2026-10-31 03:04:12 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#1126
No description provided.