Docker installeren op Rocky Linux of AlmaLinux
Installeer Docker Engine via dnf op Rocky Linux of AlmaLinux. Los direct de conflicten op met Podman en pas SELinux labels toe voor correcte bind mounts in uw containers.
Docker installeren op Rocky Linux en AlmaLinux
Om Docker te installeren op Rocky Linux of AlmaLinux voegt u de eigen dnf-repository van Docker toe, installeert u de engine met de compose-plugin en schakelt u vervolgens de service in. Dat proces bestaat uit vier commando's en is identiek op beide distributies, aangezien beide rebuilds zijn van Red Hat Enterprise Linux (RHEL) en dezelfde pakketstructuur delen. CentOS Stream werkt op dezelfde manier. Alles hieronder is van toepassing op beide, dus als u nog tussen de twee moet kiezen, zijn de bepalende factoren de compatibiliteitsbelofte die elk project doet en of uw oudere CPU nog wordt ondersteund.
De installatie is kort, dus het grootste deel van deze handleiding behandelt de verschillen tussen Enterprise Linux (EL) en Ubuntu. Podman kan het docker-commando op uw image al in gebruik hebben. SELinux blokkeert bind-mounted bestanden totdat deze het juiste label hebben. Firewalld filtert de gepubliceerde poorten van Docker niet, waardoor een containerpoort open kan staan voor het internet terwijl firewall-cmd rapporteert dat er niets open staat.
Gebruik niet het gemaksscript van get.docker.com. De documentatie van Docker zelf geeft aan dat dit niet wordt aanbevolen voor productieomgevingen. Het herschrijft uw repository-configuratie zonder toestemming en kan niet veilig opnieuw worden uitgevoerd voor upgrades. Door de repository handmatig toe te voegen, behandelt dnf upgrade Docker als elk ander pakket op het systeem. Hierdoor valt de engine ook onder het beheer van dnf-automatic, als u dit gebruikt om beveiligingsupdates op een timer toe te passen, dus beslis tijdig of u wilt dat Docker automatisch wordt gepatcht of dat u dit liever in een onderhoudsvenster doet. Hoe dan ook, een upgrade vervangt het geïnstalleerde binaire bestand terwijl de oude dockerd blijft draaien, en needs-restarting is het commando dat aangeeft welke services nog steeds de code draaien die u zojuist hebt vervangen.
Beantwoordt podman al het docker-commando?
Rocky Linux en AlmaLinux leveren podman in hun standaardrepositories en veel VPS-images installeren dit al voor u. Sommige images gaan verder en installeren podman-docker, wat een shellscript plaatst op /usr/bin/docker dat podman aanroept. Elk docker-commando dat u typt, voert vervolgens podman uit, waardoor een handleiding geschreven voor Docker resultaten geeft die u niet verwachtte.
Het eerste teken is een banner. Het /usr/bin/docker-script controleert op het bestand /etc/containers/nodocker, en wanneer dat bestand ontbreekt, print het één regel voordat het iets uitvoert:
Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.Iemand kan dat bestand hebben aangemaakt om de banner te onderdrukken, dus vertrouw hier niet alleen op. Vraag de pakketdatabase welk pakket de binaire eigenaar is:
command -v docker
rpm -qf "$(command -v docker)"Een antwoord dat begint met podman-docker betekent dat podman antwoordt. Een antwoord dat begint met docker-ce-cli betekent de echte Docker. Als rpm -qf rapporteert dat geen enkel pakket eigenaar is van het bestand, heeft iemand het handmatig geïnstalleerd en dient u het script te lezen voordat u het vertrouwt.
Podman voert dezelfde OCI-images uit en is een redelijke keuze. Als u dit wilt, stop dan hier. Beide zijn Linux-containerengines, dus als de beslissing over het platform nog openstaat, is het goed om te weten dat FreeBSD jails isoleren een volledige userland in plaats van gelaagde images uit een registry te draaien. Als u Docker Engine wilt, verwijder dan eerst de conflicterende pakketten. Dit is de lijst die Docker documenteert voor RHEL:
sudo dnf remove docker docker-client docker-client-latest docker-common \
docker-latest docker-latest-logrotate docker-logrotate docker-engine podman runcLees wat dnf van plan is mee te nemen voordat u bevestigt. Op een verse VPS-image is de lijst kort. Op een server die al in gebruik is, kan het verwijderen van podman leiden tot het verwijderen van cockpit-podman of een andere tool die daarvan afhankelijk is.
Podman naast Docker behouden is in principe mogelijk: verwijder alleen podman-docker, zodat de naam docker vrij is, en runc, dat door het containerd.io-pakket wordt vervangen. De documentatie van Docker behandelt podman als een conflicterend pakket, dus deze opzet wordt niet door Docker ondersteund. Als de installatie nog steeds een conflict rapporteert, gebruik dan de volledige verwijderlijst hierboven.
Docker-repository toevoegen met dnf config-manager
Docker publiceert RPM's voor Enterprise Linux op download.docker.com. Het repository-bestand verwijst naar de CentOS-tree, waar Rocky Linux en AlmaLinux tegenaan resolven. Een Rocky-server naar een CentOS-repository laten wijzen lijkt een fout, totdat u weet hoe beide distributies voortkwamen uit de CentOS-lijn nadat Red Hat in 2020 van CentOS een Stream-versie maakte. Gecontroleerd in augustus 2026: Docker documenteert deze repository voor CentOS Stream 9 en CentOS Stream 10.
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repoVersie 5 van dnf heeft het --add-repo-argument verwijderd, waardoor het tweede commando op nieuwere releases faalt. Controleer welke versie u heeft en kies de bijbehorende vorm:
dnf --versionAls de output een 5.x-versie toont, gebruik dan de subcommand-vorm:
sudo dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/centos/docker-ce.repoBeide schrijven hetzelfde bestand naar /etc/yum.repos.d/docker-ce.repo. De verkeerde vorm faalt met een foutmelding over een onbekend argument in plaats van stilzwijgend iets fout te doen, dus u zult het niet missen.
Dat repo-bestand stelt baseurl in op een pad dat $releasever bevat, en dnf expandeert die variabele op basis van uw release-pakket. Rocky Linux en AlmaLinux stellen dit in op het major-versienummer, dus 9 op EL 9 en 10 op EL 10; dit is de reden waarom een CentOS-repository correct resolve op een Rocky-systeem. Controleer de expansie voordat u de installatie uitvoert:
sudo dnf repoinfo docker-ce-stableLees de Repo-baseurl-regel. Deze moet eindigen op /9/x86_64/stable of /10/x86_64/stable. Als uw release $releasever instelt op een puntversie zoals 9.6, rapporteert dnf Status code: 404 voor die URL bij het ophalen van metadata. Los dit op door /etc/yum.repos.d/docker-ce.repo te bewerken en $releasever te vervangen door het kale major-nummer.
De engine en de compose-plugin installeren
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginEr zijn vijf pakketten, die elk een specifieke taak uitvoeren. docker-ce is de daemon, dockerd. docker-ce-cli is het docker-commando dat u invoert. containerd.io is de container-runtime die door de daemon wordt aangestuurd. docker-buildx-plugin bouwt images. docker-compose-plugin levert docker compose als subcommando.
Deze pakketten installeren geen docker-compose-binary met een koppelteken. Dat was Compose v1, waarvan de ondersteuning in juli 2023 is beëindigd. Alles wat docker-compose met een koppelteken aanroept, moet worden bijgewerkt naar docker compose met een spatie.
De eerste installatie pauzeert om de ondertekeningssleutel van Docker te importeren en toont u de vingerafdruk. De sleutel is afkomstig van gpgkey=https://download.docker.com/linux/centos/gpg in het repo-bestand dat u zojuist heeft toegevoegd; vergelijk de vingerafdruk die dnf weergeeft met die URL voordat u deze accepteert.
Eén fout komt vaak genoeg voor om te benoemen. Als dnf meldt dat containerd.io afhankelijk is van container-selinux en dit niet kan worden gevonden, is uw AppStream-repository uitgeschakeld. Voer dnf repolist uit en controleer of appstream in de lijst staat, aangezien container-selinux daar wordt geleverd op EL 9 en EL 10.
Start Docker en controleer of het actief is
sudo systemctl enable --now docker
sudo systemctl status docker --no-pager
sudo docker run --rm hello-worldRPM-pakketten van Docker laten de daemon na installatie gestopt en uitgeschakeld. Daarom staat deze stap op de CentOS-pagina van Docker en niet op de Ubuntu-pagina, waar het deb-pakket de service automatisch voor u start. Sla enable niet over; anders draait Docker slechts tot de volgende herstart, waarna de service stopt en alle containers onbereikbaar worden.
systemctl status hoort Active: active (running) weer te geven. De hello-world-container moet This message shows that your installation appears to be working correctly. afdrukken en afsluiten. Als er in plaats daarvan een toegangsrechtenfout op /var/run/docker.sock verschijnt, bent u sudo vergeten; de sectie over de docker-groep hieronder lost dit op.
Controleer de compose-plugin afzonderlijk, aangezien dit een ander pakket is dat kan ontbreken terwijl de engine correct functioneert:
docker compose versionEen correcte reactie ziet eruit als Docker Compose version v2.x.x. Het automatisch starten van uw services na een herstart staat los van het inschakelen van de daemon, en restart policies bepalen of Compose-services na het opstarten weer actief worden.
Waarom geeft een bind mount een permission denied-fout?
Rocky Linux en AlmaLinux draaien SELinux (Security-Enhanced Linux) standaard in enforcing-modus. Controleer dit met getenforce, wat Enforcing weergeeft.
Docker-containers draaien onder het SELinux-type container_t, en dit type mag alleen bestanden lezen en schrijven die het label container_file_t hebben. Een map die u op de host aanmaakt, krijgt het label van het bovenliggende pad, wat niet container_file_t is. De container krijgt toegang geweigerd, ook al lijken de eigenaar, groep en rechten vanaf de host correct. U kunt dit reproduceren met drie commando's:
sudo mkdir -p /srv/site
echo hello | sudo tee /srv/site/index.html
sudo docker run --rm -v /srv/site:/usr/share/nginx/html:ro nginx:alpine cat /usr/share/nginx/html/index.htmlDe container geeft de volgende melding:
cat: can't open '/usr/share/nginx/html/index.html': Permission deniedTwee commando's tonen de oorzaak. ls -ldZ /srv/site toont het label, dat voor een pad onder /srv gelijk is aan system_u:object_r:var_t:s0, en niet container_file_t. Vervolgens toont sudo ausearch -m avc -ts recent het audit-logboek van de kernel, dat avc: denied { read } bevat, een scontext=-veld met de naam container_t, en een tcontext=-veld met het label dat u zojuist op de map zag. Het verschil tussen deze twee velden is de volledige verklaring.
De oplossing is een achtervoegsel aan het volume-argument. Docker herlabelt het pad dan voor u:
sudo docker run --rm -v /srv/site:/usr/share/nginx/html:ro,z nginx:alpine cat /usr/share/nginx/html/index.html:z in kleine letters herlabelt de inhoud als gedeeld, zodat meerdere containers dezelfde map kunnen gebruiken. :Z in hoofdletters herlabelt het als privaat en niet-gedeeld, gekoppeld aan één container; een tweede container die hetzelfde pad leest, krijgt dan toegang geweigerd. Gebruik :z voor alles wat ook door een sidecar of een backup-container wordt benaderd. Gebruik :Z voor een databasemap die eigendom is van één container.
De documentatie van Docker bevat een waarschuwing die het herhalen waard is, omdat het herlabelen recursief is. Het bind-mounten van een systeemmappen zoals /home of /usr met :Z "maakt uw hostmachine onbruikbaar en het kan nodig zijn om de bestanden op de hostmachine handmatig te herlabelen". Gebruik deze achtervoegsels alleen bij mappen die u zelf voor de container heeft aangemaakt, nooit bij een systeempad.
In Compose plaatst u het achtervoegsel in dezelfde string:
services:
web:
image: nginx:alpine
volumes:
- /srv/site:/usr/share/nginx/html:ro,zEr zijn twee limieten waar u gemakkelijk tegenaan loopt. De vlag --mount kan geen SELinux-label instellen, dus gebruik -v wanneer u er een nodig heeft. Benoemde volumes hebben geen achtervoegsel nodig, omdat Docker de mappen die het onder /var/lib/docker/volumes aanmaakt zelf labelt.
Schakel SELinux niet uit. Gebruik sudo setenforce 0 alleen als een test van één minuut: als de container daarna werkt, is het probleem een label en is :z het antwoord. Zet het direct terug met sudo setenforce 1. Op Enterprise Linux heeft permission denied bij een bind mount twee afzonderlijke oorzaken die er vanuit de container identiek uitzien. De ene is het SELinux-label. De andere is het reguliere numerieke eigendom van gebruiker en groep, wat is wat de PUID- en PGID-variabelen oplossen. ls -lnZ toont u de rechten, de numerieke eigenaar en het label op één regel, zodat u kunt zien met welk probleem u te maken heeft.
Waarom is een gepubliceerde poort bereikbaar terwijl firewalld gesloten lijkt?
Firewalld is de standaard firewall op Rocky Linux en AlmaLinux. Controleer of deze actief is met sudo systemctl is-active firewalld. Als u deze nog niet heeft geconfigureerd op deze machine, is SSH en een webpoort openen met firewalld de eerste stap, omdat de onderstaande verrassing pas logisch is zodra u een werkende set zone-regels heeft om mee te vergelijken. Publiceer nu een poort en bekijk wat firewalld als open beschouwt:
sudo docker run -d --name web -p 8080:80 nginx:alpine
sudo firewall-cmd --list-portsfirewall-cmd geeft een lege regel terug. Vanaf een andere machine geeft curl -I http://YOUR_SERVER_IP:8080/ de waarde HTTP/1.1 200 OK terug. De poort staat open voor het internet en uw firewall rapporteert niets.
De oorzaak is het pad dat het pakket aflegt. De zone-regels van firewalld filteren verkeer dat aan de host zelf is gericht. Een gepubliceerde poort is niet aan de host gericht: Docker installeert een destination NAT-regel (network address translation) die de bestemming herschrijft naar het adres van de container voordat het pakket het input-pad van de host bereikt, waardoor de kernel het pakket doorstuurt in plaats van het lokaal af te leveren. Docker plaatst vervolgens zijn bridge-interfaces in een firewalld-zone genaamd docker met als target ACCEPT, en voegt een forwarding-beleid genaamd docker-forwarding toe dat forwarding van elke zone naar de docker-zone toestaat. Uw zone-regels zien het pakket nooit.
De schoonste oplossing vereist geen firewall-regel. Bind de host-kant van de publicatie aan loopback en plaats er een reverse proxy voor:
sudo docker rm -f web
sudo docker run -d --name web -p 127.0.0.1:8080:80 nginx:alpine
curl -I http://127.0.0.1:8080/De lokale curl geeft HTTP/1.1 200 OK terug en hetzelfde verzoek vanaf een andere machine maakt geen verbinding meer. Alles zonder host-adres in het -p-argument wordt op elke interface gepubliceerd, dus beschouw een kale -p 8080:80 als een besluit om die service publiekelijk bloot te stellen.
Wanneer u een service wel bereikbaar wilt maken vanaf bepaalde adressen en niet vanaf andere, reserveert Docker een chain voor u. DOCKER-USER wordt verwerkt vóór de eigen accept-regels van Docker, dus een regel die u daar plaatst, blijft behouden nadat Docker herstart en zijn chains herschrijft:
sudo iptables -I DOCKER-USER -i enp1s0 ! -s 203.0.113.10 -j DROP
sudo iptables -S DOCKER-USERGebruik de interfacenaam uit ip route show default in plaats van uit te gaan van eth0, aangezien huidige EL-images namen gebruiken zoals enp1s0 of ens3. Op Rocky en AlmaLinux is het iptables-commando een compatibiliteitslaag bovenop nftables, en de chains van Docker zijn daarin zichtbaar. Regels die op deze manier zijn toegevoegd, zijn na een reboot verdwenen tenzij u ze opslaat, dus schrijf ze in een systemd-unit zodra u tevreden bent met het resultaat.
Docker Engine 28.0, uitgebracht in 2025, heeft een vergelijkbaar lek gedicht: directe gerouteerde toegang tot containerpoorten die nooit zijn gepubliceerd, wordt nu geblokkeerd in de DOCKER-chain. Die wijziging heeft geen invloed op gepubliceerde poorten, dus alles hierboven is nog steeds van toepassing op huidige versies. Het is aan te raden om de volgende operationele gewoonte aan te nemen: test na elke sudo firewall-cmd --reload een gepubliceerde poort opnieuw. Als deze niet meer reageert, installeert sudo systemctl restart docker de regels van Docker opnieuw.
Ubuntu-beheerders lopen tegen hetzelfde probleem aan via een andere tool, wat wordt uitgelegd in waarom gepubliceerde Docker-poorten ufw-regels negeren. Het NAT-pad is in beide gevallen de oorzaak. Alleen de firewall ervoor verschilt.
Een niet-rootgebruiker toevoegen aan de docker-groep
Het typen van sudo voor elk docker-commando wordt na verloop van tijd omslachtig, en de docker-groep maakt dit overbodig:
sudo usermod -aG docker $USER
newgrp docker
docker run --rm hello-worldusermod -aG bewerkt /etc/group, maar uw huidige shell beschikt al over de groepslijst, waardoor de wijziging pas van kracht wordt bij een nieuwe sessie. newgrp docker start een shell met de groep toegevoegd, zodat u direct kunt testen. Nieuwe SSH-sessies nemen de wijziging automatisch over.
Wees u bewust van wat deze groep toestaat. Lidmaatschap geeft schrijftoegang tot /var/run/docker.sock, en alles wat met die socket kan communiceren, kan de daemon verzoeken een container te starten die het bestandssysteem van de host mount. Eén commando laat zien wat dat betekent:
docker run --rm -v /:/host alpine wc -l /host/etc/shadowDit leest een bestand dat alleen door root gelezen kan worden, uitgevoerd vanaf een account zonder sudo-rechten. De eigen post-installatiedocumentatie van Docker stelt hetzelfde: de docker-groep verleent privileges die gelijkstaan aan root. Voeg alleen een account toe aan deze groep als u dat account ook sudo zou geven. Als u accounts op een nieuwe server instelt, neem dit besluit dan gelijktijdig met de rest van uw least-privilege gebruikersconfiguratie op een VPS in plaats van achteraf.
Docker biedt ook een rootless-modus die de daemon uitvoert als een niet-geprivilegieerde gebruiker. Dit is een apart installatiepad en het verandert de werking van storage drivers en poorten onder 1024, dus plan dit als een op zichzelf staand project in plaats van als een instelling die u later toevoegt.
Vervolgstappen
U beschikt nu over de engine, de compose-plugin, een service die een herstart overleeft en de drie EL-specifieke gedragingen die hierboven zijn gedocumenteerd. De volgende stap is een compose.yaml per service, en de anatomie van een Compose-bestand behandelt het bestandsformaat en de commando's die dit aansturen. Als dit uw eerste container-host is, behandelt Docker draaien op een VPS de vragen over dimensionering, opslag en image-hygiëne die in deze handleiding buiten beschouwing zijn gelaten.
FAQ
Werkt de CentOS-repository van Docker op Rocky Linux en AlmaLinux?
Ja. Voeg https://download.docker.com/linux/centos/docker-ce.repo toe met dnf config-manager. De baseurl in dat bestand bevat $releasever. Rocky Linux en AlmaLinux breiden dit uit naar het major-versienummer; een EL 9-systeem verwijst dus naar de CentOS 9-tree en een EL 10-systeem naar de CentOS 10-tree. Controleer de uitbreiding met sudo dnf repoinfo docker-ce-stable en lees de Repo-baseurl-regel. Een Status code: 404 tijdens het ophalen van metadata door dnf betekent dat de variabele is uitgebreid naar een point-release. Dit is op te lossen door /etc/yum.repos.d/docker-ce.repo te bewerken en het kale major-nummer te gebruiken.
Kunnen Docker en podman op dezelfde server worden geïnstalleerd?
De documentatie van Docker vermeldt podman en runc als conflicterende pakketten en adviseert beide te verwijderen voordat Docker Engine wordt geïnstalleerd. Het concrete conflict is het podman-docker-pakket, dat eigenaar is van /usr/bin/docker en elk docker-commando omzet in een podman-commando. Voer rpm -qf "$(command -v docker)" uit om te zien welk pakket eigenaar is van dat pad. Als de uitvoer begint met podman-docker, reageert podman. Het behouden van beide engines is geen configuratie die Docker ondersteunt; kies daarom op een belangrijke server voor één van beide.
Waarom krijg ik 'permission denied' bij een bind mount voor mijn container?
SELinux staat standaard in enforcing-modus op Rocky Linux en AlmaLinux. Containers draaien onder het type container_t en mogen alleen bestanden benaderen met het label container_file_t. Een map die u zelf heeft aangemaakt, heeft het verkeerde label, waardoor toegang wordt geweigerd, ongeacht de eigenaar of de rechten. Controleer dit met ls -ldZ op het host-pad en sudo ausearch -m avc -ts recent, dat avc: denied toont met de twee niet-overeenkomende contexten. Voeg :z toe aan het volume-argument voor inhoud die wordt gedeeld tussen containers, of :Z voor inhoud die privé is voor één container. Wijs :Z nooit naar /home of /usr, omdat de herlabeling recursief is en de host zal beschadigen.
Moet ik een poort openen in firewalld om een containerpoort te publiceren?
Nee, en dat is juist het probleem. De NAT-regel van Docker herschrijft het bestemmingsadres voordat het pakket het input-pad van de host bereikt, waardoor de zone-regels van firewalld het verkeer niet inspecteren. Docker plaatst zijn bridges bovendien in een firewalld-zone genaamd docker met target ACCEPT. Een container die is gestart met -p 8080:80 is bereikbaar vanaf het internet, terwijl sudo firewall-cmd --list-ports niets weergeeft. Publiceer naar een specifiek adres met -p 127.0.0.1:8080:80 wanneer alleen de host de service mag bereiken, of voeg filterregels toe aan de DOCKER-USER-chain, die Docker verwerkt vóór zijn eigen accept-regels.
Is het veilig om mijn gebruiker toe te voegen aan de docker-groep?
Dit verleent root-rechten. Een lid van de docker-groep kan schrijven naar /var/run/docker.sock, en docker run --rm -v /:/host alpine wc -l /host/etc/shadow leest vervolgens een bestand dat alleen toegankelijk is voor root, vanaf een account zonder sudo-rechten. De post-installatiedocumentatie van Docker bevestigt deze gelijkwaardigheid. Voeg alleen accounts toe die u al zou vertrouwen met sudo, en blijf sudo docker gebruiken voor gedeelde accounts of service-accounts. Rootless-modus is het alternatief wanneer u containers wilt draaien onder een gebruiker zonder privileges; dit is een apart installatiepad en geen instelling.