How to use Docker Compose: a guide for sysadmins and MSPs

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. Originally released as a Docker CLI plugin in 2021 under the V2 label, 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), was deprecated in 2022. Support, including security patches, ended in mid-2023, and the standalone binary was permanently removed from Docker Desktop and CI runner images (such as GitHub Actions) in April 2025. If you still see docker-compose with a hyphen in scripts or pipelines, they are already broken or about to be. 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:

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

On RPM-based distributions (RHEL, CentOS Stream, Fedora, Rocky Linux) 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.1.4 or later). If you see a v2.x version, your distribution package may be outdated: check that you are pulling from the official Docker repository. 

Installing the legacy standalone binary (docker-compose) is no longer supported: the V1 binary has been removed from all official distribution channels since April 2025. It should only be considered in exceptional backward-compatibility scenarios on legacy systems that cannot be upgraded, and even then it will no longer receive any updates or security patches. 

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; keeping it will trigger deprecation warnings in current Docker Desktop releases. 

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 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. If you manage Compose stacks that resolve remote files (for example via the include directive or OCI registries), make sure you’re running an up-to-date version of Docker Compose V5, 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.The same compose.yaml can 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.

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 supports backup of virtual machines, databases, and the data that powers your containerized applications.

Read related articles