What is Docker Compose?
Author: Domeny.ForSale editorial team Published
In brief: Docker Compose is a tool for defining and running applications made up of several Docker containers. In a single file, you describe the services, their configuration, connections and data storage, then start them with the command docker compose up. It is useful, for example, when a project needs an application, a database and an additional administration panel.
How Docker Compose works with Docker
Docker runs programs in containers: isolated environments containing an application and the dependencies it needs. A container is created from an image—a ready-made package that specifies what should be run. Compose does not replace Docker: it uses Docker to manage a set of related containers.
Without Compose, you can start each container with a separate docker run command, manually specifying ports, environment variables and the network. Compose lets you save these settings in a compose.yaml file. This allows you to store the configuration alongside the project code and reproduce it on another computer.
The fundamental concept is a service, which is a definition of a particular component of the environment, such as a database. Compose creates containers based on these definitions. By default, it also creates a project network in which services can find one another by name.
What goes in the compose.yaml file
The configuration is written in YAML, a text format that uses indentation to define its structure. Indentation must be consistent; use spaces, not tabs.
The most common elements are:
services— the list of services that make up the environment.image— the image used to start the container; an alternative isbuild, which specifies how to build your own image.ports— a mapping from a port on the computer to a port in the container, allowing access to the service from outside the container network.environment— environment variables that configure the program.volumes— mounting directories or volumes, which are data storage locations independent of the container’s lifecycle.
Starting the containers does not necessarily mean the application is working correctly. The database may need time to initialise, and the application should be able to retry its connection. depends_on can specify the startup order, but in its basic form it does not guarantee that a service is ready; that requires an appropriate health check configuration, using healthcheck, and a dependency condition.
Example: PostgreSQL and a database administration panel
Suppose you want to test PostgreSQL locally without installing the database directly on your system. You also need the Adminer panel, which lets you browse data through a web browser. Create a project directory and save a compose.yaml file in it:
services:
db:
image: postgres:17
environment:
POSTGRES_USER: demo
POSTGRES_PASSWORD: local_demo_password
POSTGRES_DB: demo
volumes:
- db_data:/var/lib/postgresql/data
adminer:
image: adminer:5
ports:
- "127.0.0.1:8080:8080"
volumes:
db_data:
Start the environment from that directory:
docker compose up -d
The -d option starts the containers in the background. On the first run, Docker will download the images if they are not available locally.
Open http://localhost:8080 in your browser. In the panel, select PostgreSQL and enter db as the server, demo as the user, local_demo_password as the password and demo as the database. If the database is still initialising, wait a moment and try logging in again.
The name db works inside the Compose network. Do not use localhost there: from the Adminer container’s perspective, it would mean the Adminer container itself, not the database. In this example, PostgreSQL does not have a port exposed on the computer, while the panel is accessible only through the computer’s local interface.
This is a configuration for learning, not a production-ready setup. Do not use the example password for real data or store real secrets in the repository.
Commands for everyday work
The current command is docker compose, with a space. The form docker-compose, found in older tutorials, refers to an older way of installing the tool. You can check whether Compose is available with docker compose version; if the command does not work, check the installation method for your system in the official Docker documentation.
| Command | Purpose |
|---|---|
docker compose ps | Shows the project’s containers and their status. |
docker compose logs -f | Displays logs and follows new messages. |
docker compose stop | Stops containers without removing them. |
docker compose down | Removes containers and the project network, but preserves named volumes by default. |
docker compose config | Validates and displays the resulting configuration. |
Be careful with docker compose down -v: the -v option also removes volumes managed by the project, so in this example it will delete the database’s data. A volume keeps data persistent after a container is removed, but it is not a substitute for a backup.
When Compose is enough, and when it is not
Compose is well suited to local application development, integration testing and simple deployments on a single server. It is particularly useful when several people need to run the same set of services without manually recreating the settings.
It does not, on its own, provide management of a cluster of multiple servers or high availability. A production deployment requires separate planning for security, backups, monitoring and image updates. An image tag such as postgres:17 may point to successive releases in the same release line; when you need strict reproducibility, consider pinning the image to a specific digest—an identifier of its contents.
To get started, run the example, check the logs and run docker compose down, followed by docker compose up -d again. This lets you see in practice the difference between a recreated container and preserved data.
See also: What is an ETF?
