Skip to main content
Docker Basics Tutorial
CHAPTER 08 Beginner

Docker Compose Fundamentals

Updated: May 15, 2026
25 min read

# CHAPTER 8

Docker Compose Fundamentals

1. Introduction

By now, you understand the agony of launching a multi-tier application using raw Docker CLI commands. To start a simple web app and a database, you have to create a network, create a volume, type a massive docker run command for the database with 5 environment variables, and then type another massive docker run command for the web server with port mappings. If you make a typo, the app crashes. Docker Compose solves this by allowing you to define your entire multi-container architecture in a single, elegant YAML text file.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Define the purpose of Docker Compose.
  • Understand the syntax of a docker-compose.yml file.
  • Define Services, Networks, and Volumes in Compose.
  • Execute docker-compose up to launch entire application stacks.
  • Execute docker-compose down to tear down infrastructure cleanly.

3. Beginner-Friendly Explanation

Imagine orchestrating a symphony.
  • Docker CLI (The Old Way): You are the conductor. You have to walk over to the violinist, tap them, and say "Start playing now." Then you run over to the cellist and say, "Start playing, but read this specific sheet music." By the time you get to the trumpets, the violins have stopped. It is exhausting and chaotic.
  • Docker Compose: You write down the entire musical score (The YAML file). You hand it to the orchestra, step onto the podium, and tap your baton once (docker-compose up). Every single musician instantly starts playing in perfect harmony.

4. The Anatomy of a docker-compose.yml File

A Docker Compose file is written in YAML (Yet Another Markup Language). Indentation is critical—you must use spaces, not tabs.

Here is a complete architecture defined in code:

yaml
123456789101112131415161718192021222324
version: '3.8'

services:
  # Service 1: The Database
  db:
    image: mysql:8.0
    volumes:
      - db-data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=secretpassword
      - MYSQL_DATABASE=myapp

  # Service 2: The Web Server
  web:
    image: php:8.2-apache
    ports:
      - "8080:80"
    volumes:
      - ./src:/var/www/html
    depends_on:
      - db

volumes:
  db-data:

5. Breaking Down the File

  • version: Specifies the Compose specification version.
  • services: The individual containers you want to run (e.g., db and web). *Note: The names you give the services (db, web) automatically become their DNS hostnames on the network!*
  • image: The blueprint to pull from Docker Hub.
  • ports: Equivalent to the -p flag.
  • volumes: Maps local code or defines Named Volumes.
  • environment: Passes secret variables (like passwords) into the container.
  • depends_on: Tells Compose to start the db container *before* starting the web container.

6. The Magic Commands

Once your YAML file is written, you manage the entire architecture with two commands:
  • docker-compose up -d: Reads the YAML file, automatically creates a custom network, creates the volumes, pulls the images, and starts all the containers in the correct order in the background (-d).
  • docker-compose down: The ultimate cleanup command. It elegantly stops all containers, deletes them, and deletes the custom network, returning your computer to a perfectly clean state. *(Note: It deliberately does NOT delete Named Volumes, so your database data remains safe for the next up command!).*

7. Mini Project: Build a Multi-Container App

Let's build a Web Server + Database stack in seconds.

Step-by-Step Tutorial:

  1. 1. On your laptop, create a folder named my-compose-app. Open your terminal and cd into it.
  1. 2. Inside, create a folder named src. Inside src, create index.php with the text: <?php echo "Hello from Compose!"; ?>.
  1. 3. In the root my-compose-app folder, create a file named exactly docker-compose.yml.
  1. 4. Paste the exact YAML code provided in Section 4 of this chapter into the file and save it.
  1. 5. In your terminal, run the magic command:

bash
1
docker-compose up -d
  1. 6. Watch the terminal output! Compose will say:
  • *Creating network "my-compose-appdefault"*
  • *Creating volume "my-compose-appdb-data"*
  • *Creating my-compose-appdb1 ... done*
  • *Creating my-compose-appweb1 ... done*
  1. 7. Open your browser to http://localhost:8080. Your app is live!
  1. 8. When you are finished, clean it all up:
bash
1
docker-compose down

8. Real-World Scenarios

A new developer joins a company. The company application requires a Node.js API, a React Frontend, a PostgreSQL database, a Redis Cache, and a RabbitMQ message broker. Instead of spending 3 days reading documentation on how to configure this massive architecture locally, the developer runs git pull, types docker-compose up, and has the entire enterprise stack running on their laptop in 2 minutes.

9. Best Practices

  • Never Hardcode Secrets: In our example, we wrote MYSQLROOTPASSWORD=secretpassword directly in the YAML file. If you push this to GitHub, you are hacked. Instead, use an .env file! Create a file named .env containing DBPASS=secret, and update your Compose file to read: MYSQLROOTPASSWORD=${DBPASS}. Docker Compose automatically injects the .env variables securely.

10. Common Mistakes

  • YAML Indentation Errors: Because YAML relies on visual indentation (spaces) to define hierarchy, pressing "Tab" or accidentally adding an extra space will cause docker-compose up to fail with cryptic parsing errors. Always use a modern code editor (like VS Code) that highlights YAML formatting errors visually.

11. Exercises

  1. 1. If you define a service named api and a service named database in the same docker-compose.yml file, how does the api code connect to the database? What hostname does it use?
  1. 2. What happens to the Custom Network and the Named Volumes when you execute docker-compose down?

12. FAQs

Q: What is the difference between docker-compose and docker compose? A: Historically, Docker Compose was a separate Python program you had to install separately, invoked with docker-compose (with a hyphen). Recently, Docker integrated Compose directly into the core Docker CLI as a plugin, invoked with docker compose (with a space). Both generally work identically on modern systems, but the space version is the modern standard.

13. Interview Questions

  • Q: Explain the paradigm shift of utilizing Docker Compose over raw Docker CLI commands. How does Compose adhere to the principles of Infrastructure as Code (IaC)?
  • Q: Describe the function of the dependson directive in a Docker Compose file. Does dependson guarantee that a database is fully initialized and ready to accept connections before the web server starts? *(Hint: No, it only waits for the container process to start. Look up wait-for-it scripts!)*

14. Summary

In Chapter 8, we elevated our workflow from manual container management to orchestrated infrastructure automation. We introduced Docker Compose as an Infrastructure-as-Code tool, translating complex, multi-container architectural requirements into a simple, declarative YAML file. We learned how a single docker-compose up command automates network creation, volume provisioning, and container execution, drastically accelerating developer onboarding and testing environments.

15. Next Chapter Recommendation

We have the tools to orchestrate containers. Now, let's dive deep into specific technologies. Proceed to Chapter 9: Running Web Servers with Docker.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·