Course outline

Docker / Compose and reliable runtime contracts / Lesson 7

Compose projects and resolved configuration

Treat a Compose file as a declarative model with explicit project scope and review the resolved result before lifecycle actions.

About 4 min readContent reviewed
On this page

Lesson goals

  • Explain services, networks, volumes, project identity, and build versus run.
  • Inspect interpolation, merge behavior, and canonical configuration safely.

A service is a desired runtime definition

Compose describes related services and supporting resources. A service is a model, not a permanent container id; recreating it can replace its process and endpoint while retaining separately managed volumes. The project name scopes generated resources and prevents accidental collisions between environments. Choose that name deliberately and use the same file set and project options during inspection and lifecycle work, otherwise commands may address a different application instance.

Read a complete single-service model

The following model assumes the earlier app.py and Dockerfile are in the context directory. build declares how an image can be produced; image names the resulting or selected image. Declaring both does not mean every inspection command rebuilds or starts it. The loopback publication is for the synthetic local lab. No real secret, persistent business state, or production availability claim is embedded in this example.

yaml Complete compose.yaml for the fixture
name: parcel-lab
services:
  api:
    build:
      context: .
      dockerfile: Dockerfile
    image: parcel-api:lab
    ports:
      - "127.0.0.1:18080:8080"

The project is parcel-lab and the logical service is api. The default network allows future same-project peers to address api:8080. The published host URL is 127.0.0.1:18080. Actual build content, generated container names, and running state require separate evidence; parsing the file proves none of those runtime outcomes.

Resolve the model without starting services

docker compose config parses files, resolves supported interpolation, and renders the canonical model. --quiet checks validity without printing the model; --services lists service names. These are configuration operations rather than proof of daemon health or a successful deployment. Full rendered output can contain interpolated credentials, so prefer quiet validation or a narrowly selected nonsecret view in shared logs. Review the working directory and explicit -f arguments used to choose files.

bash Review-only configuration checks
docker compose -f compose.yaml config --quiet
docker compose -f compose.yaml config --services
Expected output
api

For this complete one-service model, the services view contains api. Quiet success would have no normal output, but no CLI execution is claimed here. Unknown fields, unresolved required variables, or invalid types should be fixed in the source model before any approved runtime operation.

Multiple files require field-specific reasoning

A base file and an override form one resolved model, but not every list behaves like a simple replacement. Merge rules and uniqueness keys affect ports, volumes, and other fields. Paths also follow Compose's documented base-file resolution rules. Do not assume an override removed an exposure just because it added another port. Inspect the combined result with exactly the deployment file order and keep environment-specific differences small and reviewable.

Separate validation, build, replacement, and removal

A valid configuration may still reference an unavailable image or a port already owned by another process. A successful build may still fail at runtime. Container replacement changes process identity, whereas volume retention follows separate settings and policy. Document which operator owns each transition and which state must survive. Broad teardown or cleanup commands are not appropriate diagnostic defaults, especially in a shared daemon where unrelated projects may coexist.

Common errors and fixes

Additional property is not allowed.

Why it happens
A service option is misspelled or placed under the wrong Compose object.
How to fix it
Compare the field with the current specification and inspect indentation.
Prevent it next time
Validate the exact merged model before runtime changes.

The expected containers are missing from the project view.

Why it happens
Different project naming, file options, or daemon context selected another scope.
How to fix it
Establish the intended project and context before concluding resources were lost.
Prevent it next time
Record effective project options in operational runbooks.

An override unexpectedly keeps a published port.

Why it happens
Merge semantics were mistaken for unconditional list replacement.
How to fix it
Inspect the canonical combined model and apply supported field-specific override semantics.
Prevent it next time
Review effective exposure rather than only the override diff.

Check your understanding

1. Does config --quiet prove parcel-api is serving requests?

Show worked solution

No. It validates the configuration model without demonstrating image availability, application startup, network reachability, or readiness. Keep those verification stages separate. A useful release record states which checks actually ran and preserves evidence rather than translating one successful parse into a deployment claim.

2. Why must inspection use the same -f order as deployment?

Show worked solution

Later files can alter or extend earlier fields according to merge rules. A different sequence can produce another effective image, mount, environment, or port set. Inspecting only the base file may therefore approve a model that is never actually used by the intended environment.

Key takeaways

  • Project identity and resolved configuration are part of the runtime contract.
  • A valid model is one verification stage, not proof of an operational service.

Official references