Docker Compose Overview
Docker Compose becomes useful when your application stops being “one container.” Instead of remembering a sequence of commands to create networks, start containers, attach volumes, and configure everything correctly, you describe the application once and let Compose manage those pieces together.
What Is Docker Compose?
So far, you’ve been managing Docker resources individually.
For example, imagine an application that needs:
- an application container
- a database container
- a user-defined network so they can communicate
- a volume so database data survives container removal
Without Compose, you would manage each resource separately.
Conceptually, it looks something like this:
Create network
↓
Create volume
↓
Create database container
↓
Connect database to network
↓
Create application container
↓
Connect application to network
↓
Start everythingAnd when you’re finished, you’d have to manage those resources individually again.
This works perfectly well for learning Docker and for simple situations. But as the number of containers and supporting resources grows, manually managing them becomes tedious and error-prone.
Docker Compose changes the way you think about the application.
Instead of thinking:
“Which Docker commands do I need to run?”
you start thinking:
“What does my application consist of?”
You describe that application in a Compose file, and Compose uses that description to create and manage the required Docker resources.
The mental model is:
Without Compose
Docker commands
│
├── network
├── container
├── container
└── volumeWith Compose:
compose.yaml
│
┌────────────┼────────────┐
│ │ │
services networks volumes
│
┌────┴────┐
│ │
app databaseThe important change isn’t simply that Compose gives you shorter commands.
Compose lets you describe a multi-container application as one declarative configuration.
From Containers to Applications
A Docker container is an individual unit.
But a real application is often made from several containers that need to work together.
For example:
Application
│
┌─────┴─────┐
│ │
app database
│ │
└─────┬─────┘
│
networkThe application isn’t just the app container.
It is the combination of:
- the containers
- how those containers communicate
- persistent storage
- configuration
- and the relationships between these resources
Compose gives you a way to describe that whole application.
This is why Compose is especially useful when you have multiple containers that belong to the same application.
Declarative vs Manual Management
There is an important conceptual difference here.
When you manually run Docker commands, you’re telling Docker what to do right now.
For example:
Create this network.
Create this container.
Attach it to that network.
Create this volume.
Start another container.With Compose, you describe what the application should look like.
For example:
This application has:
an app service
a database service
a network
a volume
The app uses the network.
The database uses the network.
The database uses the volume.Compose then works out the Docker resources needed to make that description happen.
That’s the difference between an imperative approach and a declarative approach.
You don’t have to memorize those terms to use Compose, but the idea is worth remembering:
Manual Docker commands describe actions. Compose describes the desired application.
What Does Compose Manage?
A Compose project can describe several types of resources.
At the center are services.
A service represents a container-based component of your application.
For example:
services
├── app
└── databaseA Compose file can also describe supporting resources such as:
services
├── app
└── database
networks
└── application network
volumes
└── database storageSo instead of keeping the application’s configuration scattered across many Docker commands, you keep it together in one Compose configuration.
Later in this chapter, you’ll build this up piece by piece.
Compose Manages the Application as a Unit
This is one of the most useful ideas to keep in mind throughout this chapter.
Suppose your application consists of:
app container
database container
application network
database volumeWithout Compose, you think about four separate Docker resources.
With Compose, you think about one application made from several resources:
Compose Project
│
┌──────────────┼──────────────┐
│ │ │
app database storage
│ │ │
└─────────── network ─────────┘You can then operate on the application as a unit rather than manually coordinating every individual resource.
This becomes particularly valuable when you repeatedly need to create the same environment.
For example, another developer can take the Compose configuration and recreate the same application structure on their machine instead of receiving a long list of Docker commands to execute manually.
Compose And The Docker Concepts You Already Know
Compose Is Not a Replacement for Docker
Compose doesn’t replace the Docker concepts you’ve already learned.
It builds on them.
You still have:
- images
- containers
- networks
- volumes
Compose provides a way to describe and manage those resources together.
Think of it like this:
Docker
│
├── Images
├── Containers
├── Networks
├── Volumes
│
└── Compose
│
└── describes and manages
applications built from those resourcesSo the networking and volume concepts you’ve already learned are directly relevant here.
When you later write a Compose file with a network or volume, you aren’t learning a completely different networking or storage system. You’re describing Docker resources that you already understand.
The Compose File
The central piece of a Compose project is a file such as:
compose.yamlThis file describes the application.
At a high level, you can think of it as:
compose.yaml
│
├── services
│ ├── app
│ └── database
│
├── networks
│
└── volumesYou don’t need to understand the YAML syntax yet.
For now, the important thing is the role of the file:
The Compose file is the description of your application’s Docker environment.
The next lesson will start with the smallest useful Compose file and build the syntax from there.
Why Use Compose?
Compose becomes increasingly useful as your application grows.
1. Fewer Manual Commands
Instead of maintaining a long sequence of Docker commands, the application’s configuration lives in one place.
2. Repeatable Environments
If the same Compose configuration is used on another machine, the application can be recreated from that configuration.
This is particularly useful for development environments where several containers need to work together.
3. One Application, One Configuration
The relationship between containers, networks, and volumes becomes visible in one place instead of being spread across shell history or documentation.
4. Easier Lifecycle Management
Starting and stopping a multi-container application becomes an application-level operation.
You don’t have to think of the application as a collection of unrelated containers.
What Compose Does Not Magically Solve
Compose is powerful, but it isn’t magic.
A Compose file still needs to describe the application correctly.
For example, if two services need to communicate, you still need to understand networking. If a database needs persistent data, you still need to understand volumes.
Compose gives you a better way to express and manage those relationships; it doesn’t remove the underlying Docker concepts.
That’s why the topics you’ve already covered matter.
You learned networks before Compose, so now you’ll describe networks through Compose.
You learned volumes before Compose, so now you’ll describe volumes through Compose.
The same Docker concepts are still underneath.
The Mental Model to Remember
Keep this picture in mind as you move through the rest of the chapter:
Manual Docker
────────────────────────────────
Individual commands
│
├── create network
├── create container
├── create container
├── create volume
├── connect resources
└── start resources
Docker Compose
────────────────────────────────
compose.yaml
│
▼
┌─────────────────┐
│ Application │
├─────────────────┤
│ services │
│ networks │
│ volumes │
│ configuration │
└─────────────────┘
│
▼
Docker resourcesDocker gives you the building blocks. Compose lets you describe how those building blocks form an application.
In the next lesson, you’ll write the smallest possible Compose file and see exactly how that description turns into a running container.