Skip to main content
In this lesson you’ll run the same voting application stack using Docker Compose instead of starting each container manually. Docker Compose lets you define the entire multi-container stack in a single YAML file and bring it up or tear it down with a single command. Below are the manual steps (kept for reference) that mirror what the Compose configuration will do.

Manual steps (reference)

  1. Create a network:
  1. Start Redis and Postgres:
  1. Build the application images locally:
  1. Run the application containers and publish ports:
Confirm images and containers:
Example (condensed) output for images:
If you have images but no running containers, docker ps will show no entries.
Now we’ll convert those manual steps into a Docker Compose file so the entire stack can be started with a single command.

Compose file: reference configuration

Create a Compose file (for example simple.yaml) in your project directory. The first version uses pre-built images (mirrors the manual docker run approach):
Notes:
  • vote and result need port mappings to expose their web UIs: 8080:80 and 8081:80.
  • redis is redis:alpine and does not need a published port for internal service-to-service networking.
  • The Postgres service defines environment variables and a named volume db-data to persist database data.
Run the stack:
What Compose does when you run up:
  • Creates a default network (project_name_default) unless you define one explicitly.
  • Creates and starts containers for each service.
  • If run in attached mode (default), logs for all services stream to your terminal with a service-name prefix.
Example (truncated) startup output:
Open the apps in your browser: To stop services started in attached mode, press Ctrl+C. To remove the containers, network, and default volumes created by Compose:
Docker Compose automatically creates a project network (derived from the directory name) if you don’t explicitly define one. You don’t need to manually create voting-app unless you have a specific reason to reuse a pre-existing network.

Build images with Compose (build from local Dockerfiles)

You don’t need to build images manually before using Compose. Replace image: with build: to instruct Compose to build images from local Dockerfiles. Example:
Run the build-and-up flow:
Compose will:
  • Build the vote, result, and worker images from the specified directories.
  • Start the entire stack once images are built.
Typical build-and-up logs:
Stop and clean up:
If you add -v to docker compose down -v, it will remove named volumes like db-data and delete persisted database data. Use with caution if you need to retain Postgres state between runs.

Quick reference — services, ports, and persistence

Troubleshooting tips

  • Duplicate-key DB errors: If you see Postgres duplicate-key errors, it’s usually because the database wasn’t cleaned between runs and a worker retried an insert for an ID that already exists.
  • Hostname resolution: Compose services resolve each other by service name. If a service cannot reach Redis or Postgres, ensure the hostnames used in your code match the Compose service names (e.g., redis, db).
  • Follow logs for a specific service:
  • Rebuild a specific service without restarting others:

Summary

Using Docker Compose:
  • Simplifies launching multi-container applications with a single YAML definition.
  • Supports both using pre-built images (image:) and building from local Dockerfiles (build:).
  • Handles networking, service orchestration, and volume management for you.
Useful links and references:

Watch Video

Practice Lab