Document docker-compose.<host>.yml fallback for list-replacement deltas
This commit is contained in:
+45
-19
@@ -46,38 +46,64 @@ Some stacks run on **multiple hosts** with the same image but slightly different
|
||||
|
||||
```
|
||||
Charlie/<stack>/
|
||||
├── docker-compose.yml # the "what" — same on every host
|
||||
├── docker-compose.yml # the "what" — default, used by hosts without an override
|
||||
├── docker-compose.<host>.yml # full per-host compose (when the delta is structural)
|
||||
├── envs/
|
||||
│ ├── morgott.env # per-host env (Ansible host_vars equivalent)
|
||||
│ ├── melina.env
|
||||
│ ├── mohg.env
|
||||
│ └── miquella.env
|
||||
├── overrides/ # only when env can't express it (volumes, services)
|
||||
│ └── miquella.yml # Kustomize overlay equivalent — usually absent
|
||||
├── deploy.sh # picks env + override based on `hostname -s`
|
||||
├── overrides/ # additive overlay deltas (when env can't express it)
|
||||
│ └── <host>.yml
|
||||
├── deploy.sh # picks env + compose file based on `hostname -s`
|
||||
└── README.md
|
||||
```
|
||||
|
||||
### Rules
|
||||
### Resolution order in `deploy.sh` (per host)
|
||||
|
||||
- `docker-compose.yml` is **canonical** and works on every host as long as the right env file is loaded. Use `${VAR:-default}` liberally.
|
||||
- `envs/<host>.env` is tracked in git (no secrets). Secrets-bearing values come from a separate gitignored `.env` (host-local) merged in at deploy time, OR from runtime secret sourcing (vaultwarden, deferred).
|
||||
- `overrides/<host>.yml` only exists when env vars genuinely can't bridge the difference (e.g. extra volume bind, service add/remove, network change). Aim for zero override files; one or two is acceptable.
|
||||
- `deploy.sh` is the host-side entrypoint. Always:
|
||||
```bash
|
||||
HOST=$(hostname -s)
|
||||
args=(--env-file "envs/$HOST.env" -f docker-compose.yml)
|
||||
1. If `docker-compose.<host>.yml` exists → use **only** that (full per-host compose).
|
||||
2. Else `docker-compose.yml` + (if present) `overrides/<host>.yml` layered on top.
|
||||
3. If `envs/<host>.env` exists → loaded with `--env-file` in either case.
|
||||
|
||||
Hostname is lowercased (`hostname -s | tr '[:upper:]' '[:lower:]'`).
|
||||
|
||||
### When to use which
|
||||
|
||||
| Delta type | Use |
|
||||
|---|---|
|
||||
| Different scalar value (port, env var, URL) | `envs/<host>.env` |
|
||||
| Add an extra service or scalar field | `overrides/<host>.yml` (compose merges additively) |
|
||||
| **Replace** a list (volumes, command, networks) | `docker-compose.<host>.yml` (full file) |
|
||||
| Different image | `docker-compose.<host>.yml` |
|
||||
|
||||
Compose's `!override` and `!reset` YAML tags exist for list-replacement, but support is uneven across compose versions (notably broken on Synology DSM's bundled compose). Prefer the full-file approach when replacing lists.
|
||||
|
||||
### Canonical `deploy.sh`
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
HOST=$(hostname -s | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
if [ -f "docker-compose.$HOST.yml" ]; then
|
||||
args=(-f "docker-compose.$HOST.yml")
|
||||
else
|
||||
args=(-f docker-compose.yml)
|
||||
[ -f "overrides/$HOST.yml" ] && args+=(-f "overrides/$HOST.yml")
|
||||
sudo docker compose "${args[@]}" "$@" # forward `up -d` / `pull` / `down` / etc.
|
||||
```
|
||||
fi
|
||||
[ -f "envs/$HOST.env" ] && args=(--env-file "envs/$HOST.env" "${args[@]}")
|
||||
|
||||
exec sudo docker compose "${args[@]}" "$@"
|
||||
```
|
||||
|
||||
### Mental model
|
||||
|
||||
- "What" = `docker-compose.yml`
|
||||
- "Where" = the host running `./deploy.sh` (no inventory file needed; the host knows its own name)
|
||||
- Per-host vars = `envs/<host>.env` (Ansible `host_vars`)
|
||||
- Per-host structural deltas = `overrides/<host>.yml` (Kustomize overlay)
|
||||
- Group defaults = compose env-var defaults (`${VAR:-default}`)
|
||||
- "What" = `docker-compose.yml` (or per-host file).
|
||||
- "Where" = the host running `./deploy.sh` (no inventory file; the host knows its own name).
|
||||
- Per-host vars = `envs/<host>.env`.
|
||||
- Per-host structural deltas = `overrides/<host>.yml` for additive, `docker-compose.<host>.yml` for replacement.
|
||||
- Group defaults = compose env-var defaults (`${VAR:-default}`).
|
||||
|
||||
### Once runners exist (Phase 2)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user