Deploying Multi-Container Apps with Docker Compose

Modern applications are often built from multiple connected services rather than a single container, which makes manual deployment complex and error-prone. This article explains how Docker Compose uses a simple YAML file to define, deploy, and manage multi-container applications with a single command.

Docker ComposeCompose FileMicroservices

~4 min read · Updated Sep 5, 2026

Introduction

Modern cloud-native applications are usually built from several small, connected services rather than a single monolith — an architecture known as microservices. Managing multiple related containers by hand with individual docker commands quickly becomes complex. Docker Compose, often just called Compose, solves this by letting an entire application be described in a single YAML file and deployed with one command.

Background

Compose originated as a tool called Fig, built by Orchard Labs to simplify deploying multi-container apps on top of Docker. Docker, Inc. later acquired Orchard Labs, rebranded the tool as Docker Compose, and eventually folded it directly into the Docker CLI as the docker compose subcommand. Compose is also guided by an open, community-led Compose Specification, with Docker Compose serving as its reference implementation.

All modern versions of Docker include Compose pre-installed, and its presence can be verified with:

docker compose version

Anatomy of a Compose File

A Compose file, conventionally named compose.yaml, defines an application's services, networks, and volumes. A typical example defines a web front-end service and a Redis backend, connected over a shared network, with Redis using a persistent volume:

services:
  web-fe:
    build: .
    command: python app.py
    ports:
      - target: 8080
        published: 5001
    networks:
      - counter-net
  redis:
    image: "redis:alpine"
    networks:
      - counter-net
    volumes:
      - type: volume
        source: counter-vol
        target: /app

networks:
  counter-net:

volumes:
  counter-vol:

The services key defines each microservice, including how to build or which image to pull, what command to run, which ports to expose, and which network to join. The networks and volumes keys declare the shared resources services can attach to or mount. Because both services join the same network, they can resolve and communicate with each other by service name — for example, the web app connects to Redis simply by referencing redis as the hostname.

Deploying the App

The most common way to deploy a Compose application is:

docker compose up --detach

This single command builds or pulls any required images, creates the declared networks and volumes, and starts all the defined containers. Docker names the resulting resources using a combination of the project name — derived from the build context's directory — and the service name, such as multi-container-web-fe-1.

A custom Compose file name or location can be specified with the -f flag:

docker compose -f apps/ddd-book/sample-app.yml up --detach

Managing the App's Lifecycle

Once deployed, a Compose app can be managed with a small set of dedicated subcommands. docker compose ps lists the running containers and their status, while docker compose top shows the processes running inside each container.

docker compose stop
docker compose restart

Stopping an app leaves its containers, networks, and volumes intact, so restarting it resumes exactly where it left off — including any data stored in a volume. Checking overall app status is done with:

docker compose ls

Cleaning Up

To fully remove an app, including its volumes and images, the following command can be used:

docker compose down --volumes --rmi all

By default, docker compose down only removes containers and networks, leaving volumes and images in place — a safeguard against accidentally losing stored data.

Conclusion

Docker Compose turns what would otherwise be a series of fragile, manually-run commands into a single, version-controllable definition of an application. Because a Compose file documents every service, image, port, network, and volume an application depends on, it also serves as valuable living documentation that helps bridge the gap between development and operations teams.

Written & researched by Dr. Shahin Siami

Related Articles

How Docker Uses Linux Security Technologies: Namespaces, Cgroups, and More

Docker's security model is built on layered defense, combining well-established Linux kernel technologies with sensible defaults out of the box. This article explains how namespaces, control groups, capabilities, mandatory access control, and seccomp work together to isolate and secure containers.

Continue

Managing Persistent Data in Docker with Volumes

Containers get a temporary writable layer by default, which disappears the moment a container is deleted — fine for scratch data, but risky for anything worth keeping. This article explains how Docker volumes decouple persistent data from container lifecycles, and walks through creating, using, and sharing them safely.

Continue

How Docker Overlay Networks Work: VXLAN Under the Hood

Overlay networks let containers on different hosts communicate as if they shared a single flat network, forming the backbone of most cloud-native microservices apps. This article covers how to build, encrypt, and test a Docker overlay network across a Swarm cluster, and explains the VXLAN tunneling technology powering it behind the scenes.

Continue

Connecting Docker Containers to VLANs and Load Balancing with Swarm

Beyond basic bridge networks, Docker can connect containers directly to existing physical VLANs, resolve service names automatically, and distribute traffic across a Swarm cluster. This article covers the macvlan driver, Docker's built-in service discovery, and Swarm's ingress load balancing mesh.

Continue

Understanding Docker Networking: CNM, Libnetwork, and Bridge Networks

Docker networking is built on an open design called the Container Network Model, implemented through libnetwork and extended by pluggable drivers. This article covers the theory behind Docker networking and walks through creating and testing single-host bridge networks, including name resolution and port mapping.

Continue

Deploying and Managing Multi-Node Clusters with Docker Swarm

Docker Swarm turns a group of Docker nodes into a secure, highly available cluster with built-in application orchestration. This article covers building a multi-node swarm, deploying a microservices app declaratively, and performing rolling updates without losing desired-state consistency.

Continue