Docker Compose, now at version V5, is one of the most widely adopted tools in the containerization ecosystem and, by now, a baseline skill for anyone running modern IT infrastructure. Announced as Compose V2 in 2020 and generally available since April 2022 as a Docker CLI plugin, it was rebranded to V5 in 2025 to avoid confusion with the legacy Compose file format versions (2.x and 3.x), but functionally, nothing changed.

For sysadmins and Managed Service Providers (MSPs), being fluent with it means orchestrating multi-container environments in a declarative, reproducible and versionable way – cutting down on manual errors and shortening intervention times across customer sites.

In this 2026 update we look at what Docker Compose is, how to install the current version and which commands every IT professional should keep in their daily toolkit.

What is Docker Compose?

Docker Compose is an official Docker tool that lets you define and run multi-container applications building on standard Docker containers from a single YAML configuration file. In a microservices architecture – where each component (authentication, database, frontend, reverse proxy, message queue, etc.) runs in its own container – Compose centralizes the definition of services, networks, volumes, secrets and configs in a single declarative file, removing the need to manage dozens of individual docker run commands.

For a sysadmin or an MSP this translates into three concrete operational benefits:

  • Reproducibility: the same compose.yaml file produces identical environments across developer laptops, staging servers and customer production sites.
  • Versionability: the configuration of the whole stack lives in Git alongside the code or the operational documentation, eliminating drift between environments.
  • Delivery and support speed: starting, stopping or recreating an entire application takes a single command, which simplifies deployment, maintenance and troubleshooting across heterogeneous customer fleets.

Installing Docker Compose

Docker Compose V1, the original Python binary invoked as docker-compose (with a hyphen), reached end of life in June 2023. It was removed from Docker Desktop starting with version 4.23.0 and from GitHub Actions runner images in July 2024. If you still see docker-compose with a hyphen in scripts or pipelines, check what it resolves to: on Docker Desktop it now points to the Compose V2 binary, but on GitHub-hosted runners the old V1 command fails, and any remaining V1 install is unsupported and unpatched. The current standard is Docker Compose V5 (still commonly referred to as V2 in many articles and tutorials), rewritten in Go and shipped as a Docker CLI plugin, which is invoked as docker compose (no hyphen, with a space).

Docker Desktop (Windows and macOS)

On Windows and macOS no separate installation is required: Docker Compose is bundled with Docker Desktop and is immediately available as soon as the client is installed. The up-to-date official instructions are available in the Docker documentation.

Linux (Ubuntu, Debian and derivatives)

On Linux systems, the recommended approach is to install the docker-compose-plugin package from the official Docker repository (see the full list of supported distributions), so that updates follow the normal patch cycle of the operating system. The repository must be set up first: follow the repository setup instructions for your distribution, then run:

sudo apt-get update
sudo apt-get install docker-compose-plugin

On RPM-based distributions (RHEL and compatible distributions, CentOS Stream, Fedora) the equivalent command is:

sudo dnf install docker-compose-plugin

Once installed, it is good practice to verify version and availability right away:

docker compose version

The output should show a v5.x release (for example, v5.6.0). Docker still supports the v2.x line as well, but if you see an older release, check that you are pulling from the official Docker repository so you receive the latest updates.

Installing Compose V1 (the Python docker-compose) is not supported: it reached end of life in June 2023 and receives no security patches. Docker still documents a standalone install of the V2 binary, but it is labelled legacy and the plugin remains the recommended method.

The compose.yaml file

The configuration file is the heart of Docker Compose: it contains the declarative definition of all services, networks, volumes, secrets and configs that make up the application. Put differently, a Dockerfile describes how to build a single container image, whereas the Compose file describes how to run an entire multi-container application (services, networking, storage and all).

A naming note that often causes confusion in mixed-age projects: the canonical name recommended by the Compose Specification is now compose.yaml, but Compose still automatically recognizes docker-compose.yml, docker-compose.yaml and compose.yml to ensure compatibility with existing files. For new projects it makes sense to adopt the canonical name.

Another frequent source of confusion: the version top-level key (e.g. version: “3.8”) that appears in many older tutorials and existing projects is now obsolete and ignored by Compose. Modern Compose files should start directly with services (no version declaration needed). If you encounter it in legacy stacks, it can be safely removed: Compose ignores it and prints a warning that the attribute is obsolete.

Below is a minimal example showing the typical layout of a three-tier web stack (reverse proxy, application, database) with health checks and conditional dependencies – a very common pattern in MSP contexts:

services:
  db:
    image: postgres:17
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    volumes:
      - db_data:/var/lib/postgresql/data
    secrets:
      - db_password
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - backend

  app:
    image: registry.example.com/myapp:1.4.0
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    networks:
      - backend

  proxy:
    image: nginx:1.30-alpine
    restart: unless-stopped
    ports:
      - "443:443"
    depends_on:
      - app
    networks:
      - backend

volumes:
  db_data:

networks:
  backend:

secrets:
  db_password:
    file: ./secrets/db_password.txt

For the more complex scenarios typical of enterprise and MSP environments, the Compose specification includes a number of features worth knowing from the start:

  • Profiles: enable optional services (e.g. monitoring, debugging, batch jobs) only in selected environments, avoiding the need to maintain separate files for each scenario.
  • Override files: in addition to compose.yaml, a second compose.override.yaml file is automatically merged, allowing you to keep base configuration separate from local or staging overrides.
  • Include directive: lets you compose a project from multiple independent Compose files (include: – path: ./monitoring/compose.yaml), making it easier to maintain reusable building blocks across customer stacks.
  • Configs: non-sensitive configuration data (for example, an Nginx virtual host file or an application settings file) can be declared under the configs top-level key and mounted into containers, keeping configuration separate from images and environment variables.
  • Secrets: sensitive data such as passwords and API keys are mounted as files at /run/secrets/<name> inside the container, avoiding their exposure through environment variables or baked into images.
  • Health checks with the service_healthy condition: let a service start only after its dependencies are actually operational, not merely running – a detail that makes the difference in production.

Security note: in 2025, a high-severity vulnerability (CVE-2025-62725, CVSS v4 score 8.9) was identified in how Docker Compose handles remote OCI artifacts. The issue affects versions from 2.34.0 up to (but not including) 2.40.2, and can lead to arbitrary file overwrites on the host, even when running seemingly read-only commands such as docker compose ps or docker compose config. It is fixed as of version 2.40.2, so every Compose V5 release is unaffected. If you manage Compose stacks that resolve remote files (for example via the include directive or OCI registries) on hosts still running a 2.x release, upgrade to the latest version, and avoid resolving Compose artifacts from unverified sources.

Docker Compose commands

The full command reference is available in the Docker CLI docs. All commands must be run from the directory that contains the compose.yaml file. The ones below form the daily operational flow for anyone managing containerized infrastructure.

docker compose up Builds the images (if needed), creates networks and volumes and starts the containers defined as services. Adding the -d flag (docker compose up -d) starts the stack in detached mode, which is the standard approach on production servers. If the containers are already running and the configuration has changed, Compose automatically recreates only those affected by the changes, leaving the others untouched.

docker compose start Starts containers that already exist, without rebuilding images or recreating resources. Useful after a planned stop or a node reboot.

docker compose stop Gracefully stops the running services while keeping containers, networks, volumes and images in place. It is the preferred command when you want to suspend a stack temporarily while preserving its state.

docker compose down Stops services and removes the containers and the networks created by Compose. By default, named volumes and images are left on the system: this avoids accidental loss of persistent data, a valuable safeguard in production environments.

  • docker compose down --volumes also removes the named volumes associated with the stack (destructive operation: use it only when you genuinely want to start from scratch).
  • docker compose down --rmi all removes all images used by the services.

A handful of additional commands are essential for day-to-day operations:

docker compose ps Lists the status of the containers belonging to the current stack, including health check results. This is the first command to invoke for a quick status check.

docker compose logs -f Streams the aggregated logs of all services in real time (or of a single service, by name). It is the starting point for any troubleshooting activity.

docker compose pull Updates the declared images locally, in preparation for a subsequent up to roll out new releases to production in a controlled fashion.

docker compose config Renders the fully resolved configuration, useful for validating the syntax and verifying the merge of any override files before applying them.

docker compose exec Opens an interactive session or runs a one-off command inside a running container without starting a new one. For example, docker compose exec db psql -U postgres drops you straight into a PostgreSQL shell for a quick diagnostic. It is usually the fastest path to troubleshooting a misbehaving service.

docker compose ls Lists all active Compose projects on the host, regardless of the directory you are in. For MSPs managing multiple stacks on a single server, it provides an immediate overview of what is running and where.

docker compose restart Restarts one or more services without tearing down and recreating the containers. Useful for picking up configuration changes that only require a process restart (for example, after updating an Nginx config mounted as a volume).

From setup to production

Mastering Docker Compose does not require deep Docker expertise, but for sysadmins and MSPs it is a high-return investment: it standardizes deployments, shortens the onboarding time for new customers, simplifies the operational documentation of stacks and reduces the margin for error in repetitive tasks. Because Compose is an open specification, the same compose.yaml can also be consumed by alternative runtimes such as Podman Compose, giving you flexibility if you ever need to move away from Docker Engine.

The practical advice is to start from a real scenario – for example a web application with a database and a reverse proxy – write your own compose.yaml, commit it to Git and iterate by progressively adding health checks, secrets and profiles. In a few cycles you arrive at a reusable baseline you can deploy across all your customers, with a clear net gain in reliability and response times. When a single host is no longer enough and you need scaling or high availability across multiple nodes, it is time to look at orchestrators: see Docker vs Kubernetes to understand how the two layers differ.

If you manage containerized infrastructure for multiple customers, pairing Docker Compose with a solid backup strategy and a reliable remote support workflow makes the difference between a smooth operation and a stressful one. Uranium Backup protects files and folders, databases (SQL Server, MySQL, MariaDB) and virtual machines (VMware, Hyper-V), including the data of the hosts that run your containerized applications.

Read related articles