liveBook · Manning

Docker Compose

As explained in Road to Kubernetes

The Docker Compose plugin is a Docker CLI extension that provides Docker Compose commands for defining and running multi-container applications.

A container can be easy to start once and hard to start the same way every time. A `docker run` command grows as you add ports, environment variables, volumes, and other options; several containers mean several commands to remember. Docker Compose puts those runtime choices in a YAML file, usually `compose.yaml`, so you can build and run the application with repeatable commands. It is a first step in container orchestration: making containers run as intended, initially by building and starting them. section 6.2.1 section 6.2

Start with a working application and Dockerfile. Under `services`, give each containerized application a service name. For a Python web application, `build.context` selects the build directory, `build.dockerfile` selects its Dockerfile, `ports` maps a host port to a container port, and `environment` sets variables. These replace arguments you would otherwise pass to `docker build` and `docker run`. Run `docker compose build` to build, `docker compose up` to start, and `docker compose down` to stop. For a build-and-start in one step, use `docker compose up --build`. section 6.2.2 section 6.2.1

Listing 6.3 Docker Compose for our Python app
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
      - PORT=8080

A small Python `compose.yaml` makes the translation concrete: one `web` service specifies its Dockerfile, port mapping, and `PORT` environment variable. section 6.2.2

As the application gains state, add a `volumes` entry to mount data into its container; `docker compose exec web` then runs commands inside that service without requiring its container ID. An `env_file` entry can supply variables from a `.env` file instead of putting their values in the Compose file. Keep sensitive `.env` files out of Git. Be careful with volume cleanup: `docker compose down -v` attempts to remove Compose-managed volumes, while a mounted local directory is not removed by Compose. section 6.3.2 section 6.4.3

Multiple services get a network for container-to-container communication. Within it, a service name acts as a hostname: a Python `web` container can request an NGINX service by name even when NGINX has no port published to the host. The same pattern lets a web application reach a Redis service using a host value supplied through `.env`. Host-facing port mappings and service-to-service addresses solve different problems. section 6.4.1 section 6.4.3

Listing 6.9 NGINX service in Docker Compose
services:
  my-nginx-service:
    image: nginx
  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
      - PORT=8080
    volumes:
      - mywebdata:/app/data

volumes:
  mywebdata:

The two-service configuration shows a built Python web container alongside an NGINX image. Only the web service publishes a host port; both services can use the Compose network. section 6.4.1

For another environment, select a different file with `docker compose -f compose.prod.yaml up`; a production file can choose a tagged image instead of a local build. On a virtual machine, install Docker Engine and the Compose plugin, then provide the configuration, images, and required environment values. A GitHub Actions deployment can copy the production Compose file and `.env` over SSH, run `docker compose pull`, and start containers with `docker compose up -d`. The plugin uses `docker compose`; older installations used `docker-compose`. section 7.2.2 section 7.3.3 section 7.1.3

Compose works well for a handful of development or production services, but it is not a complete answer to scaling. Its stated limits include easy replication of one service, health assessment beyond whether a container runs, remote runtime access without SSH, multi-VM deployment, and native ingress or public-IP provisioning. Duplicating services behind NGINX can provide load balancing, but adds configuration rather than removing those limits. section 7.4 section 7.4.1

How Road to Kubernetes covers it

How deep it goes
Works through service configuration, commands, networking, state, and deployment steps, then identifies scaling limits rather than covering every customization.
Examples
Uses Python and Node.js applications, plus NGINX and Redis services, to show configuration, communication, and production deployment.
What it assumes
Assumes a working application and Dockerfile for the first exercise; introduces service configuration and container networking step by step.
What you can do after
Operate/configure Docker Compose to build, start, stop, and connect services locally, then deploy tagged images on a virtual machine.
How it connects
Connects Dockerfiles and images to volumes, environment variables, container networking, CI/CD, and NGINX load balancing.

Also explained in

Compare how 15 books explain Docker Compose →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Road to Kubernetes. The section links point to the parts of the book it draws on.