Ship the compose file as an example, so a bare up cannot start it #2

Merged
branderson merged 1 commits from compose-example into main 2026-08-28 16:22:30 -07:00
Collaborator

Summary generated by LLM agent

Reported while setting it up: the container instructions said to copy docker-compose.yml to docker-compose.override.yml, edit that, and then run a bare docker compose up -d.

That is wrong twice.

docker compose up reads both files and merges them. An override does not replace the example, it layers over it — so the example values stay in play, and anything the override does not mention comes from the file with example.invalid in it.

And a committed docker-compose.yml means a bare up in a fresh clone starts something. It would come up pointed at devbox.example.invalid, fail to resolve, and report a devbox unreachable that was never configured — a max-priority alert about a machine nobody asked it to watch.

The fix

docker-compose.example.yml, copied to docker-compose.yml, which is gitignored. The same shape as etc/config.example, and the right place for a host and a couple of URLs anyway.

It also will not start as shipped

The example's host is CHANGE-ME.example.invalid, and the guard refuses that.

dejima's own nginx-dejima.conf.example takes this approach — "As written this file will not load: that is deliberate, so it can never become a live config by being copied into sites-enabled and forgotten." The same risk applies here and the same answer fits.

The refusal names the value rather than reporting the host as unreachable, because unreachable is exactly what it would otherwise look like — and "could not reach the devbox" is a real finding this design exists to surface. It should not be something the shipped example can produce.

Tested

bats test/ — 23 passing, 3 new:

  • the placeholder is refused rather than run;
  • the shipped example still carries that placeholder;
  • no docker-compose.yml is committed.

The second exists because the first stops protecting anything the moment someone puts a plausible-looking hostname in the example. A guard whose trigger has quietly been removed is worse than no guard, because it still looks like one.

**Summary generated by LLM agent** Reported while setting it up: the container instructions said to copy `docker-compose.yml` to `docker-compose.override.yml`, edit that, and then run a bare `docker compose up -d`. That is wrong twice. **`docker compose up` reads both files and merges them.** An override does not replace the example, it layers over it — so the example values stay in play, and anything the override does not mention comes from the file with `example.invalid` in it. **And a committed `docker-compose.yml` means a bare `up` in a fresh clone starts something.** It would come up pointed at `devbox.example.invalid`, fail to resolve, and report a devbox unreachable that was never configured — a max-priority alert about a machine nobody asked it to watch. ## The fix `docker-compose.example.yml`, copied to `docker-compose.yml`, which is gitignored. The same shape as `etc/config.example`, and the right place for a host and a couple of URLs anyway. ## It also will not start as shipped The example's host is `CHANGE-ME.example.invalid`, and the guard refuses that. dejima's own `nginx-dejima.conf.example` takes this approach — *"As written this file will not load: that is deliberate, so it can never become a live config by being copied into sites-enabled and forgotten."* The same risk applies here and the same answer fits. The refusal names the value rather than reporting the host as unreachable, because unreachable is exactly what it would otherwise look like — and "could not reach the devbox" is a real finding this design exists to surface. It should not be something the shipped example can produce. ## Tested `bats test/` — 23 passing, 3 new: - the placeholder is refused rather than run; - the shipped example still carries that placeholder; - no `docker-compose.yml` is committed. The second exists because the first stops protecting anything the moment someone puts a plausible-looking hostname in the example. A guard whose trigger has quietly been removed is worse than no guard, because it still looks like one.
dejima-agent added 1 commit 2026-08-28 16:18:58 -07:00
The setup said to copy docker-compose.yml to docker-compose.override.yml,
edit that, and then run a bare `docker compose up -d`. That is wrong twice.

`docker compose up` reads docker-compose.yml AND
docker-compose.override.yml, and merges them - so an override leaves the
example values in play rather than replacing them. And a committed
docker-compose.yml means a bare `up` in a fresh clone starts the guard
pointed at example.invalid, doing nothing useful and reporting a devbox
unreachable that was never configured.

It is docker-compose.example.yml now, copied to docker-compose.yml, which is
gitignored - the same shape as etc/config.example, and the place a host and
some URLs belong.

The example also will not start as shipped: its host is CHANGE-ME.example.
invalid and the guard refuses that. dejima's nginx example takes the same
approach for the same reason - a file that cannot become a live config by
being copied and forgotten. The refusal names the value rather than saying
the host is unreachable, because unreachable is what it would otherwise
look like.

Three tests: the placeholder is refused, the shipped example still carries
it, and no docker-compose.yml is committed. The second exists because the
first stops protecting anything the moment somebody puts a plausible
hostname in the example.

`bats test/` 23 passing.
branderson approved these changes 2026-08-28 16:22:22 -07:00
branderson merged commit 3e34eec29f into main 2026-08-28 16:22:30 -07:00
Sign in to join this conversation.