Docker Compose Implementatie op een VPS
TUTORIAL 8 min read fordnox

Docker Compose Implementatie op een VPS

Volledige handleiding voor het implementeren van applicaties met Docker Compose op een VPS. Van installatie tot multi-container opstellingen met netwerken en volumes.


Docker Compose Implementatie op een VPS

Docker Compose is de eenvoudigste manier om applicaties op je VPS te implementeren en te beheren. Als je op zoek bent naar de beste VPS voor Docker, bekijk dan eerst onze vergelijking. Definieer daarna je volledige stack in één bestand, implementeer met één commando en werk bij zonder downtime.

Waarom Dit Belangrijk Is

Traditionele implementaties zijn omslachtig:

Docker Compose lost dit op:

Vereisten

Stap 1: Docker Installeren

# Verwijder oude versies
sudo apt remove docker docker-engine docker.io containerd runc

# Installeer afhankelijkheden
sudo apt update
sudo apt install ca-certificates curl gnupg -y

# Voeg Docker's GPG-sleutel toe
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Voeg repository toe
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Installeer Docker
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

# Voeg je gebruiker toe aan de docker-groep (uitloggen/inloggen vereist)
sudo usermod -aG docker $USER

# Controleer de installatie
docker --version
docker compose version

Log uit en weer in zodat de groepswijzigingen van kracht worden.

Stap 2: Je Projectstructuur Aanmaken

mkdir -p ~/apps/myapp
cd ~/apps/myapp

Aanbevolen structuur:

myapp/
├── docker-compose.yml      # Hoofd compose-bestand
├── docker-compose.prod.yml # Productie-overschrijvingen
├── .env                    # Omgevingsvariabelen (nooit committen!)
├── .env.example            # Sjabloon voor omgevingsvariabelen
├── nginx/
│   └── nginx.conf          # Aangepaste Nginx-configuratie
├── data/                   # Persistente data (gitignored)
└── logs/                   # Applicatielogboeken (gitignored)

Stap 3: Je Eerste docker-compose.yml Schrijven

Laten we een complete webstack implementeren:

# docker-compose.yml
services:
  app:
    image: node:20-alpine
    working_dir: /app
    volumes:
      - ./src:/app
      - /app/node_modules
    command: npm start
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgres://user:pass@db:5432/myapp
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - internal

  db:
    image: postgres:16-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: myapp
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d myapp"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    networks:
      - internal

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certbot/conf:/etc/letsencrypt:ro
      - ./certbot/www:/var/www/certbot:ro
    depends_on:
      - app
    restart: unless-stopped
    networks:
      - internal

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data
    command: redis-server --appendonly yes
    restart: unless-stopped
    networks:
      - internal

volumes:
  postgres_data:
  redis_data:

networks:
  internal:
    driver: bridge

Stap 4: Omgevingsvariabelen Correct Gebruiken

Maak je .env-bestand aan:

# .env
DB_PASSWORD=your-super-secret-password-here
REDIS_PASSWORD=another-secret
API_KEY=your-api-key

Maak .env.example aan als documentatie:

# .env.example
DB_PASSWORD=
REDIS_PASSWORD=
API_KEY=

Commit .env nooit naar git! Voeg toe aan .gitignore:

echo ".env" >> .gitignore
echo "data/" >> .gitignore
echo "logs/" >> .gitignore

Stap 5: Productie-overschrijvingen

Maak een productiespecifiek bestand aan:

# docker-compose.prod.yml
services:
  app:
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  db:
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 1G

Implementeer met:

docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Stap 6: Veelgebruikte Docker Compose-commando’s

# Start alle services
docker compose up -d

# Bekijk logboeken
docker compose logs -f

# Bekijk logboeken van een specifieke service
docker compose logs -f app

# Stop alle services
docker compose down

# Stop en verwijder volumes (LET OP - verwijdert data!)
docker compose down -v

# Herbouwen en herstarten
docker compose up -d --build

# Herstart een specifieke service
docker compose restart app

# Bekijk actieve containers
docker compose ps

# Voer een commando uit in een container
docker compose exec app sh

# Bekijk resourcegebruik
docker stats

Stap 7: Implementaties Zonder Downtime

Voor updates zonder downtime:

# Haal nieuwe images op
docker compose pull

# Maak alleen gewijzigde containers opnieuw aan
docker compose up -d --no-deps app

Of gebruik rolling updates met meerdere replica’s:

services:
  app:
    deploy:
      replicas: 2
      update_config:
        parallelism: 1
        delay: 10s

Stap 8: Gezondheidscontroles

Voeg altijd gezondheidscontroles toe:

services:
  app:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Controleer de gezondheidsstatus:

docker compose ps
docker inspect --format='{{json .State.Health}}' container_name

Stap 9: Geheimen Beheren

Gebruik voor gevoelige gegevens Docker secrets of externe geheimenbeheerders:

services:
  app:
    secrets:
      - db_password
      - api_key
    environment:
      - DB_PASSWORD_FILE=/run/secrets/db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt
  api_key:
    file: ./secrets/api_key.txt

Stap 10: Back-upstrategie

Maak een back-upscript aan:

#!/bin/bash
# backup.sh

BACKUP_DIR="/backups/$(date +%Y-%m-%d)"
mkdir -p "$BACKUP_DIR"

# Back-up van PostgreSQL
docker compose exec -T db pg_dump -U user myapp > "$BACKUP_DIR/db.sql"

# Back-up van volumes
docker run --rm \
  -v myapp_postgres_data:/data:ro \
  -v "$BACKUP_DIR":/backup \
  alpine tar czf /backup/postgres_data.tar.gz /data

# Back-up van Redis
docker compose exec -T redis redis-cli BGSAVE
docker cp "$(docker compose ps -q redis)":/data/dump.rdb "$BACKUP_DIR/"

echo "Back-up voltooid: $BACKUP_DIR"

Praktijkvoorbeelden

WordPress met Database

services:
  wordpress:
    image: wordpress:latest
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: ${WP_DB_PASSWORD}
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wordpress_data:/var/www/html
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: ${WP_DB_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    restart: unless-stopped

volumes:
  wordpress_data:
  db_data:

Full-Stack JavaScript-app

services:
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    environment:
      - REACT_APP_API_URL=http://api:4000
    depends_on:
      - api

  api:
    build: ./api
    ports:
      - "4000:4000"
    environment:
      - DATABASE_URL=postgres://user:pass@db:5432/app
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis

  db:
    image: postgres:16-alpine
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: pass
      POSTGRES_USER: user
      POSTGRES_DB: app

  redis:
    image: redis:7-alpine
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:

Zelf-gehoste Git met Gitea

services:
  gitea:
    image: gitea/gitea:latest
    ports:
      - "3000:3000"
      - "222:22"
    volumes:
      - gitea_data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=postgres
      - GITEA__database__HOST=db:5432
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=gitea
      - GITEA__database__PASSWD=${DB_PASSWORD}
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: gitea
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: gitea
    restart: unless-stopped

volumes:
  gitea_data:
  postgres_data:

Best Practices

  1. Versies van images vastleggen - Gebruik postgres:16-alpine, niet postgres:latest
  2. Gebruik .env-bestanden - Houd geheimen buiten compose-bestanden (zie onze VPS-beveiligingshandleiding)
  3. Benoemde volumes voor data - Gebruik geen bind mounts voor databases
  4. Gezondheidscontroles overal - Weet wanneer services echt klaar zijn
  5. Resourcelimieten - Voorkom dat doorgedraaide containers je server neerhalen
  6. Logboeklimieten - Stel max-size in om te voorkomen dat de schijf volloopt
  7. Gebruik netwerken - Isoleer services die niet met elkaar hoeven te communiceren
  8. depends_on met condities - Wacht tot services gezond zijn, niet alleen gestart

Veelgemaakte Fouten om te Vermijden

Het latest-label gebruiken - Builds worden niet-reproduceerbaar

Data opslaan in containers - Data verdwijnt als de container wordt verwijderd

.env-bestanden committen - Geheimen belanden voorgoed in de git-geschiedenis

Geen gezondheidscontroles - depends_on wacht niet op de gereedheid van de app

Logboeken negeren - Ze vullen je schijf zonder limieten

Databasepoorten blootstellen - Stel alleen bloot wat externe toegang nodig heeft

Draaien als root - Gebruik de USER-instructie in Dockerfiles

Geen herstartbeleid - Containers komen niet terug na crashes

Debugtips

# Bekijk waarom een container mislukt
docker compose logs app --tail=100

# Open een shell in een actieve container
docker compose exec app sh

# Open een shell in een gestopte container
docker compose run app sh

# Bekijk containerdetails
docker inspect $(docker compose ps -q app)

# Controleer netwerkverbinding
docker compose exec app ping db

# Bekijk omgevingsvariabelen
docker compose exec app env

Veelgestelde Vragen

Hoeveel RAM heb ik nodig?

Voor kleine projecten is 2 GB meestal voldoende. Elke container heeft overhead, dus reken op ~100 MB per container plus de werkelijke appbehoeften. Hostinger VPS-plannen beginnen bij 4 GB, wat de meeste stacks comfortabel aankan.

Moet ik Docker Compose of Kubernetes gebruiken?

Docker Compose voor single-server implementaties (voor de meeste mensen). Kubernetes wanneer je multi-node clusters, automatisch schalen nodig hebt of een toegewijd DevOps-team hebt. Maak het niet ingewikkelder dan nodig.

Hoe werk ik een actieve applicatie bij?

# Haal de nieuwste images op
docker compose pull
# Maak gewijzigde containers opnieuw aan
docker compose up -d

Voor aangepaste builds: docker compose up -d --build

Kan ik Docker Compose gebruiken met Nginx Proxy Manager?

Ja! Stel geen poorten rechtstreeks bloot, maar zet containers op hetzelfde netwerk als NPM. Zie onze reverse proxy-handleiding.

Hoe bewaar ik data persistent?

Gebruik benoemde volumes (Docker beheert de locatie) of bind mounts (jij geeft het pad op). Benoemde volumes worden aanbevolen voor databases.

Wat is het verschil tussen up en start?

up maakt containers aan en start ze. start start alleen bestaande gestopte containers. Gebruik altijd up -d.


Volgende stappen: Stel geautomatiseerde back-ups in om je Docker-data te beschermen, en voeg monitoring toe om de containergezondheid bij te houden.

~/docker-compose-vps-guide/get-started

Ready to get started?

Get the best VPS hosting deal today. Hostinger offers 4GB RAM VPS starting at just $4.99/mo.

Get Hostinger VPS — $4.99/mo

// up to 75% off + free domain included

// related topics

Docker Compose VPS Docker container implementatie Docker handleiding VPS deployment

// related guides

Andrius Putna

Andrius Putna

I am Andrius Putna. Geek. Since early 2000 in love tinkering with web technologies. Now AI. Bridging business and technology to drive meaningful impact. Combining expertise in customer experience, technology, and business strategy to deliver valuable insights. Father, open-source contributor, investor, 2xIronman, MBA graduate.

// last updated: February 6, 2026. Disclosure: This article may contain affiliate links.