What Is Docker Compose? The Beginner's Guide (The compose.yaml Mental Model, Services vs Images, and the v2 Rules)

CodexFuse Team · 2026-11-03T14:49:41.387Z · 14 min read min read

What Is Docker Compose? The Beginner's Guide (The compose.yaml Mental Model, Services vs Images, and the v2 Rules)

Learning what Docker Compose is changes how you think about running software: instead of starting one container at a time with long docker run commands, you describe your whole application — the app, the database, the cache, their networks, their storage — in a single YAML file, and launch the entire stack with one command. Docker Compose is Docker's official tool for defining and running multi-container applications, and the mental model is deliberately simple: one file, one command, whole stack. This beginner's guide covers the compose.yaml mental model, how services differ from images and containers, Docker Compose vs Dockerfile, the v1-vs-v2 naming rules, the everyday command set, and the five mistakes beginners make most. If you have never run Docker at all, start with our Docker beginner guide — this page builds on it.

What Is Docker Compose, Exactly?

Docker Compose is a tool for defining and running multi-container applications, described in Docker's own documentation as the way to control "your entire application stack, making it easy to manage services, networks, and volumes in a single YAML configuration file" — and then, "with a single command, you create and start all the services." That is the whole definition: Compose turns a description of your application (the YAML file) into a running set of containers (the stack), and it can tear the stack down just as cleanly.

Here is the compose.yaml mental model to memorize: a Compose file describes services, not containers. Each service is a recipe — which image to use (or which Dockerfile to build), which ports to open, which environment variables to pass, which volumes to mount, which network to join. Compose reads your services, resolves their relationships (this service needs that database first), creates a private network, and starts each service as a container. You never touch the individual containers directly; you operate on the stack, and Compose figures out the container choreography.

The official landing page (docs.docker.com/compose, fetched November 3, 2026) frames it in one sentence: Compose "simplifies the control of your entire application stack." If Docker is the engine that runs one container, Docker Compose is the conductor that runs the whole orchestra.

How Does Docker Compose Work? The compose.yaml Mental Model

Docker Compose works by reading a YAML file — canonically named compose.yaml — that declares your stack's services, and optionally networks, volumes, configs, and secrets at the top level. (Per the Compose Specification, services is the only required top-level element: "A Compose file must declare a services top-level element as a map.") Everything else is optional plumbing you add as your stack grows.

A minimal but real docker compose yaml file looks like this:

services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgres://db:5432/app
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:16
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s

volumes:
  pgdata:

Read it top to bottom and you can narrate the whole application: a web service built from the current directory, reachable on port 8000, wired to a db service that starts only once its health check passes, with database files persisted in a named volume. That narration is the mental model — the file is the documentation of your stack. A few key service fields, verified against the official services reference (docs.docker.com/compose/compose-file/05-services, fetched November 3, 2026):

FieldWhat it does
imageStarts the service from a published image, e.g. postgres:16
buildBuilds the service's image from source (a Dockerfile) instead of pulling one
portsMaps host ports to container ports — "8000:8000" is host:container
environment / env_fileInjects environment variables; env_file reads them from a file, and environment values take precedence over env_file
volumesMounts storage into the container — the only way data survives a container restart
depends_onControls startup and shutdown order; conditions include service_started, service_healthy, and service_completed_successfully
restartPolicy applied when a container terminates — e.g. unless-stopped for a web service

Compose auto-creates a default private network for your stack, so services reach each other by service name — the web service connects to db simply by using the hostname db. No IP addresses to memorize, no manual network flags. This is the convenience docker run users notice first: networking that just works.

Services vs Images vs Containers: The One Picture to Memorize

The beginner confusion around docker compose explained usually comes down to three words — service, image, container — used as if they were interchangeable. They are not, and the distinction is the whole game:

  • An image is a frozen blueprint. It is built once (from a Dockerfile or pulled from a registry) and never changes while it runs.
  • A container is a running instance of an image. Start it, stop it, delete it — the image underneath is untouched.
  • A service is the Compose-level recipe for running containers from an image. It says which image to use, what ports to open, what environment to inject, and how it relates to the other services. One service can even scale to several containers of the same recipe.

Think of it as: the image is the cake recipe card, the container is the actual cake in the oven, and the service is the bakery order form that says "bake three of these, ice them blue, deliver them together." Compose is the bakery: you hand it the order form (compose.yaml) and it bakes, ices, and delivers.

Docker Compose vs Dockerfile: What's the Difference?

The short answer: a Dockerfile builds one image; Docker Compose orchestrates a multi-container stack. They are not competitors — they are different layers of the same workflow, and most real projects use both.

DockerfileDocker Compose
Answers the question"How do I build this one image?""How do I run this whole application?"
InputA text document of build instructions (Docker's definition: "all the commands a user could call on the command line to assemble an image")A YAML file describing services, networks, and volumes
OutputOne imageA running stack of containers
Typical commanddocker builddocker compose up
When you need itWhen you have code to package into an imageWhen your app has two or more moving parts (app + database + cache)

The relationship is direct: a Compose service's build: . field points at a Dockerfile, so Compose itself runs the build and then starts the stack. A single-container app never needs Compose; a three-container app with hand-typed docker run commands is a bug waiting for a restart. If you want the runtime fundamentals first, our guide to Docker fundamentals covers images and containers before you add orchestration.

Why Is It docker compose With a Space? The v1-vs-v2 Rule

It is docker compose with a space because docker-compose with a hyphen is the old version — Compose v1 — which Docker retired: per Docker's own announcement (January 31, 2023), "Compose V1 support will no longer be provided after June 2023," and the current migration page (updated September 3, 2026) states plainly that v1 is the Python-based tool "superseded by Compose v2," written in Go and integrated into the Docker CLI, and is "no longer maintained — migrate to v2."

The practical rules for 2026:

  1. Type docker compose (space), never docker-compose (hyphen). If an old tutorial shows the hyphen, mentally convert it; if your system has no v2 plugin, update Docker, not your habits.
  2. You do not need a version: field. Compose v2 implements the Compose Specification directly and ignores version numbers — leave the field out entirely.
  3. Keep the file minimal. The spec defaults are sane; every line in your compose.yaml should earn its place.

This is the single most common beginner stumbling block in docker compose tutorials: half the internet still shows the hyphen. When a command fails with "command not found," the cause is almost always the old binary.

compose.yaml vs docker-compose.yml: Which Name Should You Use?

Use compose.yaml — it is the canonical name in the official documentation (the Compose quickstart creates compose.yaml, and the CLI reference describes auto-lookup as traversing the working directory "looking for a compose.yaml or docker-compose.yaml file").

In practice, docker-compose.yml is still honored widely for compatibility (the 2026 Linuxize Compose guide documents it as supported), so an old file with that name will keep working. But new files should use compose.yaml: it is what the docs write, what new tooling expects, and what future-you will thank you for. If Compose "can't find the file," check you are running the command from the directory containing it — or pass -f with the exact path.

What Are the Docker Compose Commands? The Everyday Set

These eleven commands cover roughly everything a beginner does day to day, with their one-line behavior from the official CLI reference (docs.docker.com/reference/cli/docker/compose, fetched November 3, 2026):

CommandWhat it doesWhen you use it
docker compose upCreate and start containersFirst launch and every relaunch
docker compose up -dSame, detached (background)Running the stack while you work
docker compose downStop and remove containers and networksFull teardown; add -v to also remove named volumes
docker compose psList containers"What is running right now?"
docker compose logsView output from containersDebugging; -f follows live
docker compose execExecute a command in a running containerexec web bash opens a shell inside
docker compose stop / startStop / start services without removing themPausing work; keeps volumes and config intact
docker compose restartRestart service containersPicking up config changes that don't need a rebuild
docker compose pullPull service imagesRefreshing published images before up
docker compose buildBuild or rebuild servicesAfter changing code or the Dockerfile
docker compose configParse, resolve and render the compose file in canonical formVerifying your YAML before up
docker compose watchWatch build context and rebuild/refresh containers on file changesLocal development with live reload

Two beginners' notes: down removes containers and networks but keeps named volumes by default — your database data survives a down unless you add -v. And exec needs the service already running (it runs inside a container); if you need a one-off command without starting the stack, that is what docker compose run is for.

What Does docker compose up Actually Do?

Docker compose up explained in one sentence: docker compose up creates and starts all the containers your stack needs, in the right order, on a private network. The full sequence, in order, is:

  1. Parse. Compose reads compose.yaml, resolves variables and env_file entries, and renders the final configuration (the same output docker compose config shows you).
  2. Build (if needed). Services with a build field get their images built through BuildKit; services with an image field get pulled if missing.
  3. Create networks and volumes. The stack's private network is created, named volumes are created if they do not exist.
  4. Order. depends_on relationships are resolved — in our example, the database waits for its health check before the web service starts.
  5. Start. Each service becomes a running container, ports are bound, and logs stream to your terminal (or to the background with -d).

The reverse is exactly as tidy: docker compose down stops and removes the containers and the network, leaving your named volumes — and therefore your data — untouched. If you manage stacks visually instead of in the terminal, our Portainer beginner guide covers the GUI lane for the same stacks.

When Should You Not Use Docker Compose?

Do not use Docker Compose when you have a single container — docker run is simpler and adds nothing to maintain. Do not use it as a production orchestrator at real scale: Compose is a single-host tool, so when you need multiple machines, rolling updates with zero downtime, or autoscaling, that is the domain of Kubernetes or a managed orchestrator, not a YAML file.

Also be honest about what Compose does not do: it does not build images by itself (the Dockerfile does), it does not replace a CI/CD pipeline, and it does not secure your services — a compose.yaml with database passwords in plain environment values is fine on your laptop and a liability on a server. For a first real deployment target, read our what is VPS hosting explainer before putting a Compose stack on a public box.

Docker Compose v5: What's New in 2026?

Compose v5 is the current major line — the releases page for docker/compose showed v5.6.1 as the latest release when checked on November 3, 2026. For a beginner, three facts about v5 matter:

  • It is the Go rewrite, matured. v2's move from Python to a Go plugin inside the Docker CLI (the "no longer maintained" v1 migration) is now the settled, only-supported path.
  • Compose as a library is real. The v5 release notes carry a "Heads-up for users of Compose as a library" section documenting the api.Compose Go API — tooling (like Portainer-style managers) can embed Compose as code, not just shell out to the CLI.
  • Builds run on BuildKit machinery. Release changelogs track moby/buildkit upgrades and route build work through bake machinery (progress handling, parallel limits) — which is why docker compose build keeps getting faster without new flags to learn.

One caution from the research: no official v5.0.0 release date or standalone Python SDK was verifiable in the pages fetched this run, so treat any source quoting either with skepticism — the documented facts are the Go API, the BuildKit builds, and the v2-only command line. Prefer the daemonless angle instead? Our Podman beginner guide covers Docker's main alternative and its own compose-compatible workflow.

5 Docker Compose Mistakes Beginners Make

The same five errors appear in nearly every beginner's first week — all avoidable once you know the mental model:

MistakeWhy it hurtsThe fix
Typing docker-compose with a hyphenv1 is end-of-life; the command may not exist on a modern installAlways docker compose (space)
Keeping a version: fieldHarmless but misleading — v2 ignores it and old tutorials treat it as load-bearingDelete the field; the spec doesn't need it
Storing data inside the containerdown deletes containers; data written outside a volume vanishes with themMount a named volume for every database and upload directory
Hard-coding secrets in environmentPasswords end up in version control and shell historyUse env_file or real secrets management, and .gitignore the file
Running down -v casually-v deletes named volumes — your database is gone, not pausedUse plain down; reach for -v only when you truly want a fresh database

Sources

  1. Docker Docs — "Docker Compose" landing (definition, one-command stack): https://docs.docker.com/compose/
  2. Docker Docs — "Compose file reference" (Compose Specification; services/networks/volumes; v2 implements it): https://docs.docker.com/compose/compose-file/
  3. Docker Docs — "Define services in Docker Compose" (services top-level element; build/image/ports/environment/env_file/volumes/depends_on/restart fields): https://docs.docker.com/compose/compose-file/05-services/
  4. Docker Docs — "docker compose" CLI reference (command list and one-line behaviors; compose.yaml/docker-compose.yaml auto-lookup): https://docs.docker.com/reference/cli/docker/compose/
  5. Docker Docs — "Docker Compose Quickstart" (compose.yaml canonical example, named volumes, healthcheck, watch, .env, up/down): https://docs.docker.com/compose/gettingstarted/
  6. Docker Docs — "Deprecated and retired Docker products and features" / migration page (v1 Python-based superseded by Go v2; no longer maintained): https://docs.docker.com/compose/migrate/
  7. Docker Blog — "Docker Compose: What's New, What's Changing, What's Next" (January 31, 2023; v1 support ends after June 2023): https://www.docker.com/blog/new-docker-compose-v2-and-v1-deprecation/
  8. Docker Docs — "Dockerfile reference" (Dockerfile as the text document of image-build commands): https://docs.docker.com/reference/dockerfile/
  9. GitHub — docker/compose releases (v5 line; v5.6.1 latest at check; api.Compose Go API; BuildKit/bake machinery): https://github.com/docker/compose/releases
  10. Linuxize — "Docker Compose: Define and Run Multi-Container Apps" (2026 guide; compose.yaml preferred, docker-compose.yml still supported; v2 needs no version field): https://linuxize.com/post/docker-compose/
  11. TheServerSide — "Docker run vs Docker Compose" (hyphen v1 vs space v2; declarative config): https://www.theserverside.com/blog/Coffee-Talk-Java-News-Stories-and-Opinions/Docker-run-vs-docker-compose-Whats-the-difference

Frequently Asked Questions

Is Docker Compose the same as Docker?

No. Docker runs individual containers; Docker Compose defines and runs multi-container applications from a single YAML file. Compose is part of the Docker ecosystem — it needs the Docker engine underneath — but it solves a different problem: orchestrating a whole stack (app + database + cache) instead of one container at a time.

Do I need Docker Compose if I only have one container?

No. A single container is simpler with docker run, and adding a compose.yaml would be pure overhead. Compose earns its place at two or more services, when startup order, shared networks, and volumes start being painful to manage by hand.

Should the file be named compose.yaml or docker-compose.yml?

Use compose.yaml — it is the canonical name in the official documentation, and the CLI auto-discovers compose.yaml (and docker-compose.yaml) by walking up the directory tree. docker-compose.yml remains widely supported for compatibility, so old files keep working, but new files should use the canonical name.

What is the difference between docker compose up and docker compose start?

up creates and starts the stack from scratch — building images, creating networks and volumes, and honoring depends_on order. start only starts services that already exist (after a stop), without recreating anything. Use up for first launches, start/stop for pausing and resuming.

Does docker compose down delete my database data?

Not by default. down stops and removes containers and networks but keeps named volumes, so data in a volume like pgdata survives. Adding -v (docker compose down -v) deletes the named volumes too — which wipes the database. Use -v only when you deliberately want a fresh start.

Featured on Twelve Tools Hunt for Tools Featured on LaunchBuff Launch Llama Tools Launch your MCP Top Web Development Companies in the US - OnToplist.com Designer Listings Listed on SeeWhatNewAI