docker compose config validates the file against the Compose 514 Specification's schema before printing it, so a misspelled key fails at once instead of being silently ignored. --quiet reduces it to an exit code, which suits a CI step or a Git 1,932 hook. The include directive, added in Compose 2.20 (July 2023), pulls whole Compose files into another one, each keeping its own directory for relative paths and its own .env. A parent file one level up can add a database admin tool to BookNest without touching BookNest's file:
docker compose config --quiet && echo "compose.yaml is valid"
sed 's/^ image: postgres:18/ imgae: postgres:18/' compose.yaml > ../typo.yaml
docker compose -f ../typo.yaml config --quiet 2>&1 | cut -d: -f2-
printf '%s\n' 'include:' ' - booknest/compose.yaml' 'services:' ' adminer:' \
' image: adminer:5' ' ports: ["127.0.0.1:33080:8080"]' > ../stack.yaml
docker compose -f ../stack.yaml config --services
git add compose.yaml && git commit -q -m "Add compose.yaml for the API and PostgreSQL 18" \
-m "Replaces the PostgreSQL-only docker-compose.yml." && git log --oneline -1compose.yaml is valid services.db additional properties 'imgae' not allowed adminer db api 2e3d1a8 Add compose.yaml for the API and PostgreSQL 18
The typo was caught with the exact path of the bad key. The parent file lists all three services, and include refuses to load if an included resource conflicts with one in the parent, unlike merging files with -f (Per-Environment Files). The commit makes compose.yaml the definition Jenkins and Kubernetes build on. docker compose down then stops the stack and keeps the l3-booknest_pgdata volume, so the catalog is still there at the next up.