Understand the Compose settings
What each part of the practice configuration does, and which settings need care.
Open compose.yaml from the practice lab. YAML indentation defines structure: use spaces, preserve indentation, and validate after edits with sudo docker compose config --quiet.
Images, services, and processes
web is a service name, which other containers can resolve on a shared network. Its image is the packaged application. A running instance is a container. A stack is our organizational name for related services and configuration, not a separate Docker object. A Compose project groups its containers, networks, and volumes.
Traefik and Prometheus use release tags. The web and backup images are built from the included Dockerfiles, which pin their base images by digest. The backup build also verifies the upstream source checksum and applies explicit dependency updates. A Dockerfile describes the image build; Compose describes how its containers run. Pins make changes deliberate, but do not install future security fixes automatically.
command supplies application arguments. restart: unless-stopped restarts an exited process, but does not repair an unhealthy application. depends_on: [web] starts the dependency first; it does not wait for it to be ready. Database applications need readiness checks or connection retries. Compose startup order
Files and persistence
The site directory is a bind mount: an existing host path appears inside the container. read_only: true on that mount prevents the application from changing those files. create_host_path: false catches a missing path instead of silently making a directory.
metrics-data and backup-data are named volumes, managed by Docker and retained when containers are recreated. Persistent is not backed up. Export data using an application-supported method; copying a running database directory is not necessarily consistent. Docker volumes
The service-level read_only makes the container's root filesystem read-only. Writable named volumes still work. tmpfs provides disposable RAM-backed scratch space; it disappears on stop and is unsuitable for permanent data.
Ports and networks
127.0.0.1:18080:8080 means host loopback, host port 18080, container port 8080. The web container has no published port. Traefik reaches http://web:8080 through the private lab network. The access network lets the gateway and metrics service use their loopback publications. It is not an application login or a firewall policy for your other projects. The gateway also uses dns: [127.0.0.1] so missing service names are not forwarded to external DNS. Running service names still resolve through Docker. This gateway does not need internet name resolution.
Permissions and resource limits
cap_drop: [ALL] removes Linux capabilities. no-new-privileges blocks gaining privileges through mechanisms such as setuid. The one-off backup job adds CHOWN, DAC_OVERRIDE, and FOWNER so it can read a restricted password and restore file ownership and permissions. It has no network and can access only its mounted paths. Do not copy that exception into ordinary web applications or mount your host root.
mem_limit and pids_limit bound memory and process use. Too-small limits can cause crashes. The gateway's GOMEMLIMIT gives its Go runtime a softer memory target below the container limit. Bounded log files reduce unplanned disk growth; they do not replace a disk-space alert.
Environment variables and secrets
A project .env supplies Compose interpolation values such as ${PORT}. It does not automatically inject every value into containers. environment or env_file defines container variables. Never paste expanded docker compose config output into a public issue. Interpolation
The restic password is mounted as a Compose secret and read through RESTIC_PASSWORD_FILE. This avoids putting the value in YAML. Local Compose secrets are files, not an encrypted vault; protect the host file and backup access. Not every application supports file-based secret settings. Compose secrets
Next: DNS and routing.