Docker Compose — First Compose File

2 minute read

Time to write your first compose.yml from scratch. We’ll create a simple Nginx web server — no Dockerfile needed, just a compose file.


Step 1 — Create a Project Directory

mkdir ~/compose-demo && cd ~/compose-demo

Step 2 — Create an HTML File

mkdir html
cat > html/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head><title>Docker Compose Demo</title></head>
<body>
  <h1>Hello from Docker Compose!</h1>
  <p>This page is served by Nginx running in a Docker container,
     managed by Docker Compose.</p>
</body>
</html>
EOF

Step 3 — Write the Compose File

cat > compose.yml << 'EOF'
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
EOF

Let’s break down every line:

services:              # Top-level key — defines containers
  web:                 # Service name (you choose this)
    image: nginx:alpine  # Docker image to use
    ports:
      - "8080:80"      # Map host:8080 → container:80
    volumes:
      - ./html:/usr/share/nginx/html:ro  # Mount local html/ folder

Step 4 — Your Project Structure

compose-demo/
├── compose.yml
└── html/
    └── index.html

That’s it — two files. The compose file tells Docker what to run, and the HTML folder has your content.


Step 5 — Start the Stack

docker compose up -d

Expected output:

[+] Running 2/2
 ✔ Network compose-demo_default  Created
 ✔ Container compose-demo-web-1  Started

Notice what Compose created automatically:

  • Network: compose-demo_default (default network for the project)
  • Container: compose-demo-web-1 (project name + service name + instance number)

Step 6 — Test It

Open your browser to http://localhost:8080 or use curl:

curl http://localhost:8080

Expected output:

<!DOCTYPE html>
<html>
<head><title>Docker Compose Demo</title></head>
<body>
  <h1>Hello from Docker Compose!</h1>
  <p>This page is served by Nginx running in a Docker container,
     managed by Docker Compose.</p>
</body>
</html>

Step 7 — Check Status

docker compose ps
NAME                    STATUS    PORTS
compose-demo-web-1      Up        0.0.0.0:8080->80/tcp

Step 8 — View Logs

docker compose logs web
web-1  | /docker-entrypoint.sh: Configuration complete; ready for start up
web-1  | 172.18.0.1 - - [01/Jan/2025:00:00:00 +0000] "GET / HTTP/1.1" 200 ...

Step 9 — Clean Up

docker compose down
[+] Running 2/2
 ✔ Container compose-demo-web-1  Removed
 ✔ Network compose-demo_default  Removed

What Just Happened

compose.yml ──→ docker compose up ──→ ┌──────────────┐
                                       │ Network      │
                                       │ (default)    │
                                       ├──────────────┤
                                       │ Container    │
                                       │ nginx:alpine │
                                       │ port 8080→80 │
                                       │ volume mount │
                                       └──────────────┘

                docker compose down ──→ Everything removed ✓

Summary

Step Command / File
Create project dir mkdir ~/compose-demo && cd ~/compose-demo
Write compose file compose.yml with services, image, ports, volumes
Start docker compose up -d
Test curl http://localhost:8080
Check status docker compose ps
View logs docker compose logs web
Stop docker compose down

Quick Reference

Item Detail
Minimum compose file services: + one service with image:
Start in background docker compose up -d
Check status docker compose ps
View logs docker compose logs service-name
Stop and clean docker compose down
Volume mount ./local:/container/path:ro