10 Running multiple environments with Docker Compose
This chapter revisits Docker Compose as the glue for running many environments—dev, test, UAT, and more—on a single Docker Engine while avoiding the drift that plagues manual deployments. It explains how Compose’s project concept (with default names derived from the folder, or overridden with a project name) lets you run multiple copies of the same app side by side, each isolated with its own network and non-conflicting ports. The aim is portability and consistency: the same container images behave appropriately in each environment through configuration, not code changes.
The core technique is using Compose override files to layer environment-specific settings onto a shared, minimal docker-compose.yml. Overrides merge from left to right, and the docker compose config command shows the effective result before deployment. Practical patterns include per-environment ports and networks, health checks tailored to non-production needs, and careful use of project names so up and down manage the correct resources. The chapter then covers configuration injection: direct environment properties, env_file for shared key-value sets, secrets for sensitive or file-based settings, and host-level variables substituted into Compose (including a .env file to define default ports, COMPOSE_FILE, and COMPOSE_PROJECT_NAME) so teams can spin up targeted environments without editing YAML.
To reduce duplication, the chapter introduces YAML extension fields (anchors and merges) that centralize common blocks—such as logging options or shared labels—and reuse them across services, with the caveat that extensions don’t span multiple files. The closing workflow emphasizes promoting the same tested image through every environment and only changing configuration, enabling reliable reproduction and faster feedback. Compose excels at running many isolated environments on one machine, but it demands disciplined naming, consistent file usage, and automation for deployment and teardown to keep management overhead low.
Repeating a Docker Compose command to start an app doesn’t run a second copy of the app.
Docker Compose builds names for the resources it manages by including the project name.
Specifying a project name lets you run multiple copies of the same app with one Compose file.
Removing duplication with override files that add environment-specific settings
Merging a Compose file with an override file and displaying the output
Running multiple isolated application environments in containers on a single machine
Running multiple environments on one Docker Engine, using networks for isolation
You need to use the same files and project name to manage an application with Compose.
Changing application behavior by applying configuration settings in Docker Compose
Using an environment file to specify the default for Docker Compose files and project names
Using the config command to process files with extension fields and check the result
Defining very different environments for the same app using Docker Compose
Lab
In this lab I’d like you to build your own set of environment definitions for the to-do app. You’re going to put together a development environment and a test environment and make sure they can both run on the same machine.
The development environment should be the default, which you can run with docker compose up. The setup should
- Use a local database file
- Publish to port 8089
- Run v2 of the to-do application
The test environment will need to be run with specific Docker Compose files and a project name. Its setup should
- Use a separate database container
- Use a volume for the database storage
- Publish to port 8080
- Use the latest to-do application image
There are similarities here to the Compose files in the todo-list-configured exercises for the chapter. The main difference is the volume—the database container uses an environment variable called PGDATA to set where the data files should be written. You can use that along with a volume specification in your Compose files.
As you’ve seen in this chapter, there are lots of ways you can solve this. My solution is on GitHub here: https://github.com/sixeyed/diamol/blob/2e/ch10/lab/README.md.
Learn Docker in a Month of Lunches, Second Edition ebook for free