Herstellen na mislukte Docker-upgrades: socket-, service- en versie-mismatch oplossen
Een mislukte Docker-upgrade kan leiden tot een frustrerende mix van symptomen: Cannot connect to the Docker daemon, een docker.sock die niet meer klopt, dockerd die niet start, of een CLI die een andere versie verwacht dan de daemon. Dit gebeurt vaak na gedeeltelijke upgrades, gemixte repositories, een rollback die niet volledig was, of een systeem dat zowel distro-pakketten (bijv. docker.io) als Docker’s eigen pakketten (docker-ce) door elkaar heeft.
Deze tutorial helpt je systematisch herstellen. Je leert:
- Hoe je socket- en serviceproblemen (systemd) diagnosticeert en oplost
- Hoe je versie-mismatch tussen Docker CLI en daemon herkent en repareert
- Hoe je veilig opruimt (zonder data te verliezen) en opnieuw installeert
- Hoe je containerdata (images/volumes) bewaart en verifieert
- Hoe je veelvoorkomende valkuilen voorkomt (gemixte pakketten, rootless vs root, contexten)
Doelplatform: Linux met systemd (Ubuntu/Debian/Fedora/RHEL-achtigen).
Waar relevant worden distro-specifieke verschillen genoemd.
1. Begrijp de onderdelen: CLI, daemon, socket, systemd
Docker op Linux bestaat grofweg uit:
- Docker CLI (
docker): het commando dat jij typt. - Docker daemon (
dockerd): de achtergrondservice die containers beheert. - Socket (
/var/run/docker.sock): UNIX-socket waar de CLI mee praat. - systemd units:
docker.service(startdockerd)docker.socket(socket-activatie; maakt/luistert op de socket)
- Containerd (
containerd): runtime/onderlaag; Docker gebruikt dit meestal.
Wanneer upgrades mislukken, zie je vaak:
- CLI is geüpdatet, daemon niet (of andersom)
docker.servicestart niet door configfoutendocker.socketwijst naar een verkeerde locatie of heeft verkeerde permissies- Je hebt per ongeluk zowel
docker.ioalsdocker-cegeïnstalleerd
2. Symptomen en snelle triage
2.1 Veelvoorkomende foutmeldingen
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?Error response from daemon: client is newer than serverError response from daemon: client version X is too old. Minimum supported API version is Yfailed to start daemon: ...Job for docker.service failed because the control process exited with error code
2.2 Snelle statuscheck (kopieerbaar)
# Basis: werkt de CLI überhaupt?
docker version
# Systemd status
systemctl status docker --no-pager
systemctl status docker.socket --no-pager
systemctl status containerd --no-pager
# Logs (meest waardevol)
journalctl -u docker -n 200 --no-pager
journalctl -u containerd -n 200 --no-pager
# Bestaat de socket en wat zijn de rechten?
ls -l /var/run/docker.sock
stat /var/run/docker.sock
# Is dockerd actief en luistert hij?
ps aux | grep -E 'dockerd|containerd' | grep -v grep
ss -xl | grep docker
Interpretatie:
- Als
docker versional faalt met socket-error, is de daemon niet bereikbaar. - Als
systemctl status docker“failed” is, kijk direct naarjournalctl -u docker. - Als
docker versionwel output geeft maar “client/server mismatch” meldt, is het vooral een versieprobleem.
3. Socket- en serviceproblemen: systemd correct krijgen
3.1 docker.service vs docker.socket: wie start wie?
Op veel systemen kan Docker via docker.socket “on-demand” starten. De socket-unit luistert, en als er een connectie komt, start systemd docker.service.
Controleer of socket-activatie aan staat:
systemctl is-enabled docker.socket
systemctl is-active docker.socket
systemctl cat docker.socket
systemctl cat docker.service
Let op:
docker.sockethoort meestal te luisteren op/run/docker.sock(wat symlinked kan zijn naar/var/run/docker.sock).- Als je custom configuratie hebt die
-H fd://of-H unix:///...gebruikt, moet dat matchen.
3.2 Reset een “verkeerd” gestarte service (zonder data te wissen)
Als Docker in een rare toestand zit na een upgrade:
sudo systemctl daemon-reload
sudo systemctl stop docker docker.socket
sudo systemctl stop containerd
# Optioneel: oude runtime restanten opruimen (niet destructief)
sudo rm -f /var/run/docker.pid /run/docker.pid 2>/dev/null || true
sudo rm -f /var/run/containerd/containerd.sock 2>/dev/null || true
sudo systemctl start containerd
sudo systemctl start docker.socket
sudo systemctl start docker
Check daarna:
systemctl --no-pager --full status docker docker.socket containerd
docker info
3.3 Veelvoorkomende oorzaak: fout in /etc/docker/daemon.json
Een upgrade kan strenger worden op JSON of deprecated keys. Valideer je config:
cat /etc/docker/daemon.json
python3 -m json.tool /etc/docker/daemon.json
Herstart en check logs:
sudo systemctl restart docker
journalctl -u docker -n 200 --no-pager
Veelvoorkomende fouten:
- Trailing comma in JSON
- Onbekende sleutel
- Conflicterende
hosts(bijv. zowel systemd-H fd://als"hosts": [...])
Als je "hosts" definieert, wees expliciet en consistent, bijvoorbeeld:
{
"hosts": ["unix:///var/run/docker.sock"]
}
Let op: als je
"hosts"indaemon.jsonzet, kan dat botsen met systemd unit-parameters. In dat geval moet je de systemd override aanpassen (zie hieronder).
3.4 Systemd override controleren (drop-ins)
Check of er overrides bestaan die na upgrade niet meer passen:
systemctl cat docker
ls -R /etc/systemd/system/docker.service.d || true
Een typische override die problemen veroorzaakt is een oude ExecStart= regel. Als je een override hebt, controleer dat hij past bij jouw installatie.
Je kunt tijdelijk alle overrides “neutraliseren” door ze te hernoemen (veilig, om te testen):
sudo mv /etc/systemd/system/docker.service.d /etc/systemd/system/docker.service.d.bak.$(date +%F) 2>/dev/null || true
sudo systemctl daemon-reload
sudo systemctl restart docker
Als dit het oplost, zet dan een correcte override terug in plaats van de oude.
3.5 Socket permissies en docker-groep
Als de daemon wel draait maar je krijgt permissieproblemen:
# Socket rechten
ls -l /var/run/docker.sock
# Groepen
getent group docker
id
Als je user niet in de docker groep zit:
sudo usermod -aG docker "$USER"
newgrp docker
Let op:
newgrpwerkt in de huidige shell; anders opnieuw inloggen.
3.6 Rootless Docker vs rootful Docker (veelgemaakte verwarring)
Soms “werkt Docker niet”, maar je zit in de verkeerde context: rootless gebruikt vaak een socket onder je home:
- Rootful:
unix:///var/run/docker.sock - Rootless:
unix:///run/user/1000/docker.sock(of vergelijkbaar)
Check je context:
docker context ls
docker context show
docker info
Als je per ongeluk naar een rootless context wijst, zet terug:
docker context use default
Of expliciet:
export DOCKER_HOST=unix:///var/run/docker.sock
docker info
4. Versie-mismatch: client en server weer in lijn
4.1 Diagnose: docker version en API-versies
Voer uit:
docker version
Voorbeeld van mismatch:
- Client: 27.x
- Server: 24.x
Of fout:
client is newer than server
Dit kan gebeuren als:
- Alleen
docker-ce-cliis geüpdatet, maardocker-ce(daemon) niet - Je distro heeft
docker.io(daemon) en je installeerde Docker’sdocker-ce-cli - Je hebt meerdere
dockerbinaries op je PATH
4.2 Controleer welke binary je draait
which docker
type -a docker
docker --version
dpkg -S "$(which docker)" 2>/dev/null || true
rpm -qf "$(which docker)" 2>/dev/null || true
Als type -a docker meerdere paden toont (bijv. /usr/bin/docker en /usr/local/bin/docker), kan er een oude/handmatige installatie in de weg zitten.
Verwijder/rename de “vreemde” binary (bijv. in /usr/local/bin) als die niet door je pakketbeheer wordt beheerd:
ls -l /usr/local/bin/docker /usr/local/bin/dockerd 2>/dev/null || true
4.3 Controleer geïnstalleerde pakketten (Debian/Ubuntu)
dpkg -l | grep -E 'docker|containerd|runc' | sed -e 's/\s\+/ /g'
apt-cache policy docker.io docker-ce docker-ce-cli containerd.io
Typische probleemcombinatie:
docker.io(Ubuntu repo) samen metdocker-ce-cli(Docker repo)
4.4 Controleer geïnstalleerde pakketten (RHEL/Fedora)
rpm -qa | grep -E 'docker|containerd|runc'
dnf list installed | grep -E 'docker|containerd|runc'
5. Herstelstrategie: kies één “lijn” en maak het consistent
Er zijn grofweg twee gezonde paden:
- Distro-pakketten (bijv.
docker.ioop Ubuntu/Debian) - Docker’s officiële repo (
docker-ce,docker-ce-cli,containerd.io)
Meng deze niet.
5.1 Data veiligstellen vóór je ingrijpt
Docker-data staat meestal in:
/var/lib/docker(images, layers, containers)/var/lib/containerd(containerd state)- Volumes: onder
/var/lib/docker/volumes/ - Compose-projecten: jouw projectmappen (bijv.
docker-compose.yml)
Maak een snelle back-up (kan groot zijn):
sudo systemctl stop docker containerd
# Back-up naar een andere schijf/locatie
sudo tar -C /var/lib -cpf /root/docker-backup-$(date +%F).tar docker containerd 2>/dev/null || true
# Start later weer
sudo systemctl start containerd
sudo systemctl start docker
Als je weinig ruimte hebt, back-up dan minimaal je volumes of specifieke paden.
6. Oplossen door opschonen en herinstalleren (zonder data te verliezen)
Hieronder staan “harde” stappen die vaak het snelst herstellen na een mislukte upgrade. Ze verwijderen pakketten, maar laten data in /var/lib/docker staan zolang je geen purge + data-delete doet.
6.1 Debian/Ubuntu: conflicterende pakketten verwijderen
Stop services:
sudo systemctl stop docker docker.socket containerd
Verwijder bekende conflictbronnen:
# Verwijder zowel oude als mogelijke mix
sudo apt-get remove -y docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc || true
sudo apt-get remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin || true
Ruim “kapotte” dependencies op:
sudo apt-get -f install -y
sudo apt-get autoremove -y
Controleer dat /var/lib/docker nog bestaat:
sudo ls -la /var/lib/docker | head
Doe geen
apt-get purgeals je niet zeker weet wat er weg mag; purge kan configs verwijderen (meestal oké), maar data staat doorgaans elders. Verwijder ook niet/var/lib/dockertenzij je bewust alles wilt wissen.
6.2 Installeer opnieuw: kies distro of Docker repo
Optie A: Distro-pakket (Ubuntu/Debian: docker.io)
sudo apt-get update
sudo apt-get install -y docker.io
sudo systemctl enable --now docker
docker version
Optie B: Docker’s officiële repo (meestal aanbevolen voor recente features)
Installeer prerequisites:
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
Keyring en repo (voorbeeld voor Ubuntu; pas codenaam aan indien nodig):
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
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
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
docker version
Controleer dat client en server nu matchen (major/minor hoeven niet exact gelijk, maar moeten compatibel zijn).
7. Socket-mismatch: wanneer /var/run en /run door elkaar lopen
Op moderne systemen is /var/run een symlink naar /run. Toch kunnen upgrades scripts of overrides achterlaten die naar een niet-bestaande socket wijzen.
Check:
ls -ld /var/run /run
readlink -f /var/run
ls -l /var/run/docker.sock /run/docker.sock 2>/dev/null || true
Als je DOCKER_HOST hebt gezet naar een oud pad:
echo "$DOCKER_HOST"
unset DOCKER_HOST
docker info
Als je in /etc/docker/daemon.json een socket pad hebt dat niet klopt, corrigeer dat.
8. Docker start niet: gerichte loganalyse
8.1 “failed to start daemon” door storage driver
Een upgrade kan de default storage driver veranderen of je kernel/FS support beïnvloeden. Check in logs:
journalctl -u docker -n 200 --no-pager | sed -n '1,200p'
Zoek naar:
overlay2: the backing xfs filesystem is formatted without d_type supportAUFS not supportedfailed to mount overlay
Oplossingen verschillen:
- Voor XFS zonder
d_type: je moet XFS opnieuw formatteren metftype=1(ingrijpend), of een andere storage driver gebruiken (niet ideaal). - Meestal is
overlay2correct; problemen wijzen op filesystem/kernellimieten.
Check huidige driver (als Docker nog start):
docker info | grep -i "Storage Driver"
8.2 “iptables/nftables” problemen na upgrade
Soms faalt Docker door firewall backend-wissels.
Check in logs op iptables/nft errors. Relevante checks:
sudo iptables -V
sudo nft --version
Op Debian/Ubuntu kan iptables naar nftables wijzen:
sudo update-alternatives --display iptables
Docker werkt meestal met nftables tegenwoordig, maar combinaties kunnen breken. Als je bewust legacy wilt:
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
sudo systemctl restart docker
Doe dit alleen als logs duidelijk wijzen op nft/iptables incompatibiliteit. Anders creëer je nieuwe problemen.
8.3 “containerd is not running” of containerd socket errors
Docker hangt sterk af van containerd. Check:
systemctl status containerd --no-pager
journalctl -u containerd -n 200 --no-pager
Herstart:
sudo systemctl restart containerd
sudo systemctl restart docker
Als containerd faalt door config, check:
sudo test -f /etc/containerd/config.toml && sudo head -n 50 /etc/containerd/config.toml
Je kunt een default config genereren (pas op: dit overschrijft je bestaande config als je redirect gebruikt):
containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl restart docker
9. Compose en plugin-mismatch (docker compose vs docker-compose)
Na upgrades zie je vaak verwarring tussen:
docker-compose(oude Python v1, vaak EOL)docker compose(Compose v2 plugin)
Check:
docker compose version
docker-compose version || true
Als scripts nog docker-compose gebruiken, installeer óf de v1 binary (niet aanbevolen), óf update je scripts naar docker compose.
Op Ubuntu met Docker repo:
sudo apt-get install -y docker-compose-plugin
docker compose version
10. Verifieer herstel: functionele tests
10.1 Basis testcontainer
docker run --rm hello-world
10.2 Netwerk en volume test
docker network create testnet
docker volume create testvol
docker run --rm -it --network testnet -v testvol:/data alpine sh -lc \
'echo "ok" > /data/health && cat /data/health'
docker network rm testnet
docker volume rm testvol
10.3 Controleer dat je oude resources er nog zijn
docker ps -a
docker images
docker volume ls
Als je containers “weg” lijken, controleer of Docker naar een andere data-root wijst:
docker info | grep -i "Docker Root Dir"
Standaard is dat /var/lib/docker. Als dat veranderd is (bijv. door een override of daemon.json "data-root"), zet het terug of verplaats data zorgvuldig.
11. Veelvoorkomende scenario’s en concrete fixes
Scenario A: “Cannot connect … docker.sock” maar docker.service is actief
- Check socket pad en context:
docker context show
echo "$DOCKER_HOST"
ls -l /var/run/docker.sock
- Check permissies:
id
getent group docker
- Test als root:
sudo docker info
Als sudo docker info werkt, is het een permissie/groep-issue.
Scenario B: “client is newer than server”
- Bekijk versies:
docker version
- Check pakketten:
- Debian/Ubuntu:
dpkg -l | grep -E 'docker|containerd'
apt-cache policy docker.io docker-ce docker-ce-cli containerd.io
- Kies één lijn:
- Of upgrade daemon naar matchende repo
- Of downgrade CLI naar distro-versie
Meestal: installeer alles uit dezelfde repo en verwijder mix.
Scenario C: Docker start niet na upgrade door unit override
- Check unit:
systemctl cat docker
- Verwijder/disable overrides tijdelijk:
sudo mv /etc/systemd/system/docker.service.d /etc/systemd/system/docker.service.d.disabled.$(date +%s) 2>/dev/null || true
sudo systemctl daemon-reload
sudo systemctl restart docker
journalctl -u docker -n 100 --no-pager
- Bouw daarna een nieuwe override met
systemctl edit docker(netjes beheerbaar):
sudo systemctl edit docker
Voorbeeld (alleen als je weet dat je dit nodig hebt), bv. extra host:
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// -H unix:///var/run/docker.sock
Belangrijk: de lege
ExecStart=regel reset de vorige definitie; zonder die krijg je dubbele ExecStart en faalt de unit.
Scenario D: Rootless en rootful door elkaar
- Check of je rootless service draait:
systemctl --user status docker --no-pager
- Check rootful:
sudo systemctl status docker --no-pager
- Kies bewust welke je gebruikt. Voor servers meestal rootful; voor desktops soms rootless.
12. Preventie: zo voorkom je herhaling
- Gebruik één bron voor Docker pakketten (distro óf Docker repo).
- Pin versies als je productie draait:
- Debian/Ubuntu:
apt-mark hold docker-ce docker-ce-cli containerd.io
- Debian/Ubuntu:
- Controleer overrides na upgrades:
systemctl cat docker
- Bewaar daemon.json simpel; documenteer elke niet-standaard setting.
- Monitor na upgrades:
docker infojournalctl -u docker -n 50
- Maak periodiek back-ups van
/var/lib/docker/volumesen je compose-projecten.
13. Checklist: “Docker werkt weer” in 2 minuten
Gebruik deze checklist als eindcontrole:
# 1) Services actief
systemctl is-active containerd
systemctl is-active docker
# 2) Socket bestaat
test -S /var/run/docker.sock && echo "socket ok"
# 3) Versies en connectie ok
docker version
docker info | head -n 30
# 4) Run test
docker run --rm hello-world
Als alle vier slagen, zijn socket, service en versie-keten weer consistent.
14. Extra: wanneer je écht schoon wilt beginnen (destructief)
Alleen als je bewust alles wilt verwijderen (containers/images/volumes):
sudo systemctl stop docker containerd
# WAARSCHUWING: dit wist alle Docker data
sudo rm -rf /var/lib/docker /var/lib/containerd
# Daarna opnieuw installeren (zie sectie 6)
Afsluiting
De kern van herstel na mislukte Docker-upgrades is bijna altijd: consistentie. Zorg dat:
- systemd units en
daemon.jsonniet met elkaar botsen, - de socket klopt en bereikbaar is,
- client en server uit dezelfde pakketlijn komen,
- en containerd gezond is.
Als je wilt, kun je de output plakken van:
docker version
systemctl status docker docker.socket containerd --no-pager
journalctl -u docker -n 120 --no-pager
systemctl cat docker
ls -l /var/run/docker.sock
dpkg -l | grep -E 'docker|containerd|runc' || rpm -qa | grep -E 'docker|containerd|runc'
Dan kan ik gericht aangeven welke mismatch jij precies hebt en welke stappen je het best overslaat of juist wél uitvoert.