Lesson 21 / 25

Production Files With -f

Explicit file lists for each environment.

Combine files explicitly

For other environments, pass files explicitly: docker compose -f compose.yaml -f compose.prod.yaml up -d. Later files override earlier ones. A production file typically adds restart policies, resource limits, logging options, and removes development conveniences simply by not including the override. Review the merged result with config before deploying.

The production file

Restart policies and resource limits.

services:
  web:
    restart: unless-stopped
  api:
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 512M

The merged production configuration, run

I ran this with Docker Compose v2.38.1 and jq in the demo "shop" project. docker compose config parses, interpolates, merges and validates the files without starting containers; the Docker daemon was not running, so nothing was started. With -f for base and prod files, the API gets restart unless-stopped and limits of 1 CPU and 512M (normalised to 536,870,912 bytes, so M means MiB here). Because the override is not loaded, the development port 3000 is gone.

docker compose -f compose.yaml -f compose.prod.yaml config --format json | jq -c ".services.api | {restart, limits: .deploy.resources.limits, ports: [.ports[]?.published]}"

Output:

{"restart":"unless-stopped","limits":{"cpus":1,"memory":"536870912"},"ports":[]}

Quick check: Why did port 3000 disappear in the production configuration?

  • Production disables all ports
  • The automatic override file is not loaded when -f files are given
  • The prod file deletes ports explicitly
  • Port 3000 is reserved
Answer

The automatic override file is not loaded when -f files are given — Explicit -f lists replace the default file set.