Docker Compose is a tool for defining and running multi-container applications using a YAML file, traditionally named docker-compose.yml. The top-level structure has three sections: services (the containers themselves), networks (how they communicate), and volumes (shared storage). A service is defined under the services key and typically includes a build directive pointing at a directory with a Dockerfile, an image directive to use an existing image, port mappings, volume mounts, environment variables, and dependencies on other services. A typical stack might define a web service that builds from the current directory and publishes port 8080, alongside a database service that uses the postgres:15 image and mounts a named volume for its data.
Several features make Compose practical for real applications. depends_on controls startup order, ensuring a service starts only after its declared dependencies; however, by default it waits only for the container to start, not for the service to be ready, and for that you pair depends_on with condition: service_healthy and a healthcheck on the dependency. Environment variables can be set inline under environment:, loaded from a per-service env_file, or interpolated from shell variables using the ${VAR} syntax. A .env file in the same directory as the Compose file is loaded automatically, though it is distinct from env_file (which is loaded inside the container). Networks are declared at the top level and referenced by services, and services on the same network can resolve each other by name. The Compose Specification is the current open standard for the file format, making a single docker-compose.yml portable across Docker, AWS ECS, Microsoft ACI, and Kubernetes via kompose.
A few advanced features round out Compose. Profiles group services so they only start when explicitly requested with --profile, which is useful for dev-only services like debuggers or load generators. Scaling a service is done with docker compose up -d --scale web=3 for non-deploy keys, or with deploy.replicas when running in compatibility mode. The extends directive lets a service inherit configuration from another, while include (newer) merges whole YAML files into the project, which is the modern way to split Compose configurations. YAML anchors and aliases reduce duplication in large files by letting a fragment be defined once and reused across services. Common commands include docker compose up -d to start in detached mode, docker compose --build to rebuild images, docker compose down to stop and remove everything, docker compose logs to view output, and docker compose --profile debug up to activate a profile.