LANgenoten artikel

Docker en Docker Compose installeren op Debian/Ubuntu

Lees of reageer op LANgenoten →

Veel selfhosted applicaties worden aangeboden als Docker-container. Met Docker Compose kun je zo’n applicatie netjes beheren vanuit een compose-bestand.

In deze guide installeren we Docker Engine en Docker Compose op Debian of Ubuntu. Daarna maken we een simpele teststack, zodat je meteen begrijpt hoe een compose-bestand is opgebouwd.

Doel

Na deze guide heb je:

- Docker Engine geïnstalleerd

- Docker Compose geïnstalleerd

- gecontroleerd of Docker werkt

- een normale gebruiker toegevoegd aan de docker-groep

- een duidelijke mappenstructuur voor Docker Compose-stacks

- een eerste simpele compose-stack getest

- basisbegrip van poorten en volumes in Docker Compose

Voor wie is deze guide?

Deze guide is bedoeld voor mensen die een Debian- of Ubuntu-server gebruiken voor selfhosting.

Dit kan bijvoorbeeld zijn:

- een VM

- een Proxmox LXC

- een bare-metal server

- een VPS

- een mini-pc met Debian of Ubuntu Server

Let op bij Proxmox LXC

Docker in een Proxmox LXC kan prima werken, maar je container moet daar wel geschikt voor zijn.

In Proxmox heb je meestal minimaal nodig:

nesting=1

Voor sommige situaties ook:

keyctl=1

Op de Proxmox-host kun je dat bijvoorbeeld instellen met:

pct set 105 -features nesting=1,keyctl=1

Daarna de container herstarten:

pct reboot 105

Vervang 105 door het ID van jouw LXC.

Als pct reboot niet werkt omdat de container niet netjes reageert, kun je de container stoppen en daarna opnieuw starten:

pct stop 105

pct start 105

Als je net begint en zo min mogelijk gedoe wilt, kun je Docker ook in een gewone VM draaien. Dat is iets zwaarder, maar vaak voorspelbaarder.

Stap 1: Oude Docker-pakketten verwijderen

Soms staan er oude of distro-eigen Docker-pakketten op het systeem. Die kunnen conflicteren met de officiële Docker-pakketten.

Verwijder oude of conflicterende pakketten:

sudo apt remove -y docker docker-engine docker.io docker-compose docker-doc podman-docker containerd runc

Het is niet erg als sommige pakketten niet geïnstalleerd zijn. Dan meldt apt gewoon dat er niets te verwijderen is.

Let op: bestaande Docker-data in /var/lib/docker wordt hiermee niet automatisch verwijderd. Als je al een bestaande Docker-installatie had, denk dan goed na voordat je data opruimt.

Stap 2: Basisbenodigdheden installeren

Werk eerst je pakketlijst bij:

sudo apt update

Installeer daarna de benodigde pakketten:

sudo apt install -y ca-certificates curl gnupg lsb-release

Stap 3: Docker GPG-key toevoegen

Maak de keyring-map aan:

sudo install -m 0755 -d /etc/apt/keyrings

Debian

Voor Debian:

curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

Ubuntu

Voor Ubuntu:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

Zet de rechten goed:

sudo chmod a+r /etc/apt/keyrings/docker.gpg

Stap 4: Docker repository toevoegen

Nu voeg je de officiële Docker apt-repository toe.

Debian

Voor Debian:

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

Ubuntu

Voor Ubuntu:

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

Werk daarna de pakketlijst opnieuw bij:

sudo apt update

Stap 5: Docker en Docker Compose installeren

Installeer Docker Engine, containerd, Buildx en de Compose-plugin:

sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Controleer of Docker draait:

sudo systemctl status docker

Als Docker niet draait, start hem dan:

sudo systemctl enable --now docker

Stap 6: Installatie testen

Test Docker met:

sudo docker run hello-world

Als alles goed werkt, downloadt Docker een testimage en krijg je een melding dat de installatie werkt.

Controleer de Docker-versie:

docker --version

Controleer Docker Compose:

docker compose version

Als docker compose version werkt, is Docker Compose correct geïnstalleerd.

Stap 7: Gebruiker toevoegen aan de docker-groep

Standaard moet je Docker-commando’s met sudo uitvoeren.

Wil je Docker gebruiken zonder steeds sudo te typen, voeg je gebruiker dan toe aan de docker-groep.

Voor de huidige gebruiker:

sudo usermod -aG docker $USER

Of voor een specifieke gebruiker, bijvoorbeeld moofz:

sudo usermod -aG docker moofz

Log daarna uit en opnieuw in.

Of activeer de groep tijdelijk met:

newgrp docker

Test daarna:

docker ps

Als je geen foutmelding krijgt, werkt het.

Let op: gebruikers in de docker-groep hebben praktisch root-achtige rechten op het systeem. Voeg dus niet zomaar elke gebruiker toe aan deze groep.

Stap 8: Mappenstructuur kiezen

In deze guide gebruiken we /opt/stacks als basis voor Docker Compose-stacks.

/opt is volgens de Linux Filesystem Hierarchy Standard bedoeld voor optionele of third-party applicatiesoftware. Dat past goed bij selfhosted Docker-applicaties, omdat je die meestal zelf installeert en beheert.

We gebruiken daarbinnen de map stacks, zodat duidelijk is dat hier Docker Compose-stacks staan.

Voorbeelden:

/opt/stacks/nginx-proxy-manager

/opt/stacks/uptime-kuma

/opt/stacks/vaultwarden

Een stack bevat vaak meer dan alleen een compose-bestand, bijvoorbeeld:

- compose.yml

- .env

- data/

- config/

Je mag natuurlijk ook een andere map gebruiken, zoals /opt/compose, /srv/docker of /srv/stacks. Het belangrijkste is dat je consequent bent en weet waar je configuratie en data staan.

Voor beginners is dit een nette standaard:

/opt/stacks/<appnaam>

Stap 9: Mappenstructuur maken

Maak de basisdirectory aan:

sudo mkdir -p /opt/stacks

Geef je gebruiker rechten:

sudo chown -R $USER:$USER /opt/stacks

Of specifiek voor gebruiker moofz:

sudo chown -R moofz:moofz /opt/stacks

Daarna kun je per applicatie een eigen map maken.

Voorbeeld:

mkdir -p /opt/stacks/uptime-kuma

Of later:

mkdir -p /opt/stacks/nginx-proxy-manager

Mijn voorkeur is één map per compose-stack.

Bijvoorbeeld:

/opt/stacks/nginx-proxy-manager

/opt/stacks/uptime-kuma

/opt/stacks/mealie

/opt/stacks/vaultwarden

Zo blijft het overzichtelijk.

Stap 10: Eerste simpele compose-test

We maken nu een kleine teststack met Nginx. Dit is niet bedoeld als productie-webserver, maar puur om te testen of Docker Compose werkt.

Maak een testmap:

mkdir -p /opt/stacks/hello

Ga naar de map:

cd /opt/stacks/hello

Maak een compose-bestand:

nano compose.yml

Plaats hierin deze inhoud:

services:
nginx:
image: nginx:alpine
container_name: test-nginx
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./data:/usr/share/nginx/html

Sla het bestand op.

Maak daarna de map aan die we als volume gebruiken:

mkdir -p data

Maak een simpele testpagina:

echo "<h1>Docker Compose werkt!</h1>" > data/index.html

Start de container:

docker compose up -d

Controleer of hij draait:

docker ps

Open daarna in je browser:

http://IP-VAN-DE-SERVER:8080

Als alles goed werkt, zie je:

Docker Compose werkt!

Wat betekent dit compose-bestand?

Het bestand compose.yml beschrijft welke container Docker moet starten en hoe die container gekoppeld wordt aan je systeem.

services

services:

Onder services zet je één of meerdere containers die samen een stack vormen.

In dit voorbeeld hebben we maar één service:

nginx:

De naam nginx is de servicenaam binnen Docker Compose. Die mag je zelf kiezen.

image

image: nginx:alpine

Dit vertelt Docker welke image gebruikt moet worden.

In dit geval gebruiken we:

nginx:alpine

Dat is een lichte Nginx-container gebaseerd op Alpine Linux.

container_name

container_name: test-nginx

Hiermee geef je de container een vaste naam.

Daardoor zie je in docker ps duidelijk:

test-nginx

Zonder container_name maakt Docker Compose zelf een naam op basis van de map en servicenaam.

restart

restart: unless-stopped

Dit zorgt ervoor dat de container automatisch opnieuw start na een reboot of crash.

unless-stopped betekent: start automatisch opnieuw, behalve als je de container bewust zelf hebt gestopt.

Voor selfhosted services is dit meestal een handige instelling.

ports

ports:
- "8080:80"

Dit koppelt een poort op de host aan een poort binnen de container.

De notatie is:

HOSTPOORT:CONTAINERPOORT

In dit voorbeeld:

8080:80

Dat betekent:

- poort 8080 op je server

- gaat naar poort 80 binnen de Docker-container

Nginx luistert binnen de container op poort 80.

Maar vanaf je netwerk bezoek je:

http://IP-VAN-DE-SERVER:8080

Dus:

server:8080 → container:80

Een ander voorbeeld:

3001:3001

Dan wordt poort 3001 op de host gekoppeld aan poort 3001 binnen de container.

Bij een reverse proxy zoals Nginx Proxy Manager gebruik je vaak:

80:80

443:443

81:81

Omdat die poorten direct op de host beschikbaar moeten zijn.

volumes

volumes:
- ./data:/usr/share/nginx/html

Volumes koppelen een map op de host aan een map binnen de container.

De notatie is:

PAD-OP-HOST:PAD-IN-CONTAINER

In dit voorbeeld:

./data:/usr/share/nginx/html

Dat betekent:

- ./data is de map op de host

- /usr/share/nginx/html is de map binnen de container

Omdat we in /opt/stacks/hello staan, betekent ./data eigenlijk:

/opt/stacks/hello/data

Nginx gebruikt binnen de container deze map voor de websitebestanden:

/usr/share/nginx/html

Daardoor wordt onze hostmap:

/opt/stacks/hello/data

zichtbaar binnen de container als:

/usr/share/nginx/html

Als we op de host dit bestand maken:

/opt/stacks/hello/data/index.html

dan ziet Nginx dat binnen de container als:

/usr/share/nginx/html/index.html

Daarom verschijnt onze testpagina in de browser.

Waarom zijn volumes belangrijk?

Containers zijn vervangbaar. Je kunt een container stoppen, verwijderen en opnieuw maken.

Maar je data wil je behouden.

Daarom zet je belangrijke data meestal buiten de container, in volumes of bind mounts.

Voorbeelden:

./data:/app/data

./config:/config

/mnt/media:/media

/opt/stacks/app/config:/config

Links staat de hostkant. Rechts staat de containerkant.

Bijvoorbeeld:

/mnt/media:/media

betekent:

- op de host staat media in /mnt/media

- binnen de container is die media zichtbaar als /media

Relatief of absoluut pad?

In compose-bestanden kun je relatieve of absolute paden gebruiken.

Voorbeeld relatief:

./data:/app/data

Dit betekent: de map data naast je compose-bestand.

Voorbeeld absoluut:

/opt/stacks/uptime-kuma/data:/app/data

Dit wijst naar een exacte locatie op de host.

Voor beginners is relatief vaak overzichtelijk:

./data:/app/data

Dan blijft alles netjes binnen de map van de stack.

De testcontainer stoppen

Als je klaar bent met testen, kun je de container stoppen en verwijderen met:

docker compose down

De map data blijft gewoon bestaan op de host.

Wil je de testmap helemaal opruimen?

Ga dan eerst uit de map:

cd /opt/stacks

Verwijder daarna de testmap:

rm -rf hello

Let op met rm -rf. Controleer altijd goed welk pad je verwijdert.

Stap 11: Basiscommando’s

Handige Docker Compose-commando’s:

docker compose up -d

Start de stack op de achtergrond.

docker compose down

Stopt en verwijdert de containers van deze stack. Data in volumes blijft bestaan als je volumes goed hebt ingesteld.

docker compose logs -f

Bekijk live logs.

docker compose pull

Download nieuwe images.

docker compose up -d

Past updates toe na een pull.

docker ps

Toont draaiende containers.

docker ps -a

Toont alle containers, ook gestopte.

Stap 12: Updates uitvoeren

Docker zelf update je via apt:

sudo apt update

sudo apt upgrade

Containers update je per stack meestal zo:

cd /opt/stacks/naam-van-stack

docker compose pull

docker compose up -d

Ruim oude ongebruikte images af en toe op:

docker image prune

Let op: gebruik niet blind agressieve cleanup-commando’s als je niet weet wat ze verwijderen.

Stap 13: Firewall

Als je UFW gebruikt, moet je poorten toestaan die je nodig hebt.

Voor SSH:

sudo ufw allow OpenSSH

Voor een testservice op poort 8080:

sudo ufw allow 8080/tcp

Voor een reverse proxy zoals Nginx Proxy Manager heb je meestal nodig:

sudo ufw allow 80/tcp

sudo ufw allow 443/tcp

Zet alleen open wat je echt nodig hebt.

Veelgemaakte fouten

Het oude docker-compose commando gebruiken

Veel oude guides gebruiken:

docker-compose up -d

Bij moderne installaties gebruik je meestal:

docker compose up -d

Dus met een spatie.

Als docker-compose niet werkt, probeer dan docker compose.

Controleer met:

docker compose version

Geen volumes gebruiken

Zonder volumes kan data verdwijnen als je containers opnieuw maakt.

Volumes verkeerd om zetten

Bij volumes is de volgorde:

hostpad:containerpad

Dus bijvoorbeeld:

./data:/app/data

Links is de host. Rechts is binnen de container.

Als je dit omdraait, werkt je applicatie niet zoals verwacht of schrijf je data op een verkeerde plek.

Poorten verkeerd om zetten

Bij poorten is de volgorde:

hostpoort:containerpoort

Dus bijvoorbeeld:

8080:80

Links is de poort op je server. Rechts is de poort binnen Docker.

Alles in één map zetten

Dat wordt snel rommelig. Gebruik liever één map per stack.

Geen backups maken

Docker maakt beheer makkelijk, maar backups moet je nog steeds zelf regelen.

Backup minimaal:

- compose-bestanden

- configuratiebestanden

- data-volumes

- databases op applicatieniveau als dat nodig is

Containers als vervanging zien voor security

Docker is handig, maar geen magische beveiligingslaag. Houd containers up-to-date en publiceer niet zomaar alles op internet.

Docker in LXC zonder nesting

Als Docker in een Proxmox LXC vreemd doet, controleer dan of nesting aanstaat.

Te veel vertrouwen op latest

Veel compose-voorbeelden gebruiken images met de tag latest.

Dat is makkelijk, maar kan onverwachte updates geven. Voor belangrijke services kun je beter een specifieke versie gebruiken of updates bewust uitvoeren.

Checklist

Controleer na installatie:

- docker --version werkt

- docker compose version werkt

- docker run hello-world werkt

- je gebruiker kan Docker gebruiken

- /opt/stacks bestaat

- je weet waar je compose-bestanden staan

- je begrijpt het verschil tussen hostpoort en containerpoort

- je begrijpt het verschil tussen hostpad en containerpad

- je hebt nagedacht over backups

- je opent alleen noodzakelijke poorten

Samenvatting

Docker en Docker Compose zijn een goede basis voor veel selfhosted applicaties.

De belangrijkste punten:

- gebruik de officiële Docker repository

- gebruik Compose met docker compose

- maak een duidelijke mappenstructuur

- /opt/stacks is een nette plek voor selfhosted compose-stacks

- gebruik volumes voor data

- onthoud bij poorten: hostpoort:containerpoort

- onthoud bij volumes: hostpad:containerpad

- update bewust

- maak backups

- publiceer services pas als je begrijpt wat je openzet

Vanaf hier kun je verder met bijvoorbeeld Nginx Proxy Manager, Uptime Kuma, Mealie, Vaultwarden of andere selfhosted services.

Lees of reageer op LANgenoten →

← Terug naar het logboek