Ga naar hoofdinhoud

Meerdere containers beheren met Docker Compose

In het vorige hoofdstuk leerde je hoe je één container opstart. Maar een echte webapplicatie bestaat bijna nooit uit één container. Je hebt bijvoorbeeld een Node.js app én een PostgreSQL database nodig.

Beide containers apart opstarten, configureren en koppelen is omslachtig en foutgevoelig. Docker Compose lost dit op.

Wat is Docker Compose?

Docker Compose is een tool waarmee je meerdere containers definieert en beheert in één YAML-bestand. Met één commando start je alle containers tegelijk op, en met één commando stop je ze weer.

Docker Compose wordt meegeleverd met Docker Desktop. Je hoeft niets extra te installeren.

docker-compose of docker compose?

De oudere versie van Compose gebruikte het commando docker-compose (met een koppelteken). De moderne versie, die meekomt met Docker Desktop, gebruikt docker compose (met een spatie). Gebruik altijd de nieuwe variant met een spatie.

De docker-compose.yml

Je definieert je applicatie in een bestand dat je docker-compose.yml noemt. Dit bestand staat in de root van je project.

De structuur ziet er zo uit:

docker-compose.yml
services:
service-name:
image: image-name
ports:
- '8080:80'
environment:
- VARIABLE=value
depends_on:
- other-service
volumes:
- my-volume:/path/in/container

volumes:
my-volume:

De belangrijkste onderdelen:

SleutelUitleg
servicesAlle containers die je wilt draaien. Elke service is één container.
imageDe image die Docker gebruikt. Of gebruik build om een lokale Dockerfile te bouwen.
portsKoppelt een poort op je computer aan een poort in de container.
environmentOmgevingsvariabelen die de container meekrijgt.
depends_onWacht met starten totdat een andere service klaar is.
volumesKoppelt opslag aan de container, zodat data niet verloren gaat.

Een praktisch voorbeeld

We bouwen een eenvoudige setup: een Node.js app die verbinding maakt met een PostgreSQL database.

docker-compose.yml
services:
app:
build: .
ports:
- '3000:3000'
environment:
- DATABASE_URL=postgres://postgres:secret@db:5432/mydb
depends_on:
- db

db:
image: postgres:16-alpine
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=mydb
volumes:
- db-data:/var/lib/postgresql/data

volumes:
db-data:

En de bijbehorende Dockerfile voor de Node.js app:

Dockerfile
FROM node:22-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 3000

CMD ["node", "server.js"]

Wat er hier gebeurt:

  • app wordt gebouwd vanuit de lokale Dockerfile (vandaar build: .).
  • db gebruikt de officiële PostgreSQL image.
  • app krijgt de DATABASE_URL mee als omgevingsvariabele, met db als hostnaam. Docker Compose zorgt ervoor dat services elkaar via hun servicenaam kunnen bereiken.
  • depends_on zorgt dat de database eerst opstart voordat de app begint.
  • Het db-data volume zorgt dat de database-inhoud bewaard blijft, ook na het stoppen.

Compose opstarten en stoppen

Start alle services in één keer op:

Terminal
$ docker compose up

Wil je de containers op de achtergrond draaien? Gebruik de -d vlag (detached):

Terminal
$ docker compose up -d

Stop alle containers en verwijder de netwerken:

Terminal
$ docker compose down

Bekijk de logs van alle services in real time:

Terminal
$ docker compose logs -f
tip

Gebruik docker compose logs -f app om alleen de logs van één specifieke service te bekijken.

Volumes voor data

Zonder een volume verlies je alle data in je database zodra je docker compose down uitvoert. Docker gooit de container weg, inclusief alles wat erin stond.

Met een named volume slaat Docker de data op buiten de container. De volgende keer dat je opstart, staat alle data er nog. Declareer het volume altijd op twee plekken: bij de service én onderaan in het volumes blok.

docker-compose.yml (fragment)
services:
db:
image: postgres:16-alpine
volumes:
- db-data:/var/lib/postgresql/data # volume koppelen

volumes:
db-data: # volume declareren

Omgevingsvariabelen

Wachtwoorden en geheime sleutels horen niet rechtstreeks in je docker-compose.yml. Gebruik een .env bestand. Docker Compose leest dit bestand automatisch in.

.env
POSTGRES_PASSWORD=secret
DATABASE_URL=postgres://postgres:secret@db:5432/mydb
docker-compose.yml (met .env)
services:
app:
build: .
environment:
- DATABASE_URL=${DATABASE_URL}

db:
image: postgres:16-alpine
environment:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
tip

Voeg .env toe aan je .gitignore, zodat je wachtwoorden niet in versiebeheer terechtkomen. Lees meer over veilig omgaan met omgevingsvariabelen in het hoofdstuk over omgevingsvariabelen.

Handige Compose-commando's

CommandoWat het doet
docker compose upStart alle services op.
docker compose up -dStart alle services op de achtergrond.
docker compose downStopt alle services en verwijdert de netwerken.
docker compose psToont alle draaiende services en hun status.
docker compose logs -fVolgt de logs van alle services live.
docker compose exec app shOpent een shell in de app container.
docker compose buildBouwt alle images opnieuw.
docker compose restartHerstart alle services.

Met Docker Compose beheer je een volledige applicatieomgeving als één geheel. Je hoeft nooit meer individuele containers handmatig op te starten of te stoppen.

Kop koffie nodig?

Probeer De Koffiejongens met 50% korting op je bestelling. Geteeld door boeren die met de natuur werken en eerlijk betaald krijgen.