kde-redhat.org · all guides

PillarA · RHEL-family servers PublishedAugust 6, 2026 AuthorElton

How to Install Docker on AlmaLinux 10 and Rocky Linux 10

Install Docker CE on AlmaLinux 10 or Rocky Linux 10 the right way: repo, packages, the kernel module fix RHEL 10 needs, and why SELinux stays on.

TL;DR

Podman is the default on AlmaLinux 10 and Rocky Linux 10, but Docker CE still installs cleanly from Docker's own repo. The one thing that trips up fresh RHEL 10 family installs, and that most guides written for version 9 do not mention, is that dockerd refuses to start with an "addrtype revision 0 not supported" error until you install kernel-modules-extra. Everything else below is the standard path: add the repo, install, fix the kernel module, verify, run rootless, leave SELinux and firewalld exactly where they are.

$ sudo dnf install -y dnf-plugins-core
$ sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
$ sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
$ sudo dnf install -y kernel-modules-extra
$ sudo systemctl enable --now docker
$ sudo docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
Distro / kernelAlmaLinux 10.2 and Rocky Linux 10.2 (RHEL 10 family), kernel 6.12.x Docker CE version29.7.x at the time of writing (Docker ships patch builds often, expect the exact number to differ by the time you run this) Test dateAugust 6, 2026 How this was verifiedcommand syntax, package names, and the current docker-ce build were checked live against Docker's rhel/10 repo index on the test date above. The kernel-module failure and its fix were cross-checked against the docker-ce-packaging tracker (issue #1340), the docker/for-linux tracker, and Rocky Linux forum threads reporting the identical error text. NOT run end to end in a live VM in this session: the fix branch that needs a reboot cannot be exercised in a build sandbox, so treat that one command sequence as sourced, not personally reproduced today. Also appliesRHEL 10 (same repo, same commands, same kernel module gotcha)

Why Docker CE, not Podman

Red Hat has shipped Podman as the default container tool since RHEL 8, and AlmaLinux 10 and Rocky Linux 10 inherit that: no Docker package in the base repos, daemonless by design, drop-in compatible CLI. If you are starting fresh with no constraints, Podman is the tool Red Hat wants you to use and it works well. But plenty of you are not starting fresh: a CI runner expects a Docker socket, a docs page assumes docker compose, a client's stack was written against Docker Desktop and needs to run the same way on a server. Docker still publishes and maintains an official RHEL repository, and once you install it correctly, it runs fine on the RHEL 10 family. The catch is that "correctly" now includes one extra package that used to come along for free.

Step 0: a box you can afford to reboot

Disclosure: the Vultr link below is a referral. You get 300 dollars of trial credit, usable for 30 days. This site gets a commission only if you stay active past 30 days and spend 100 dollars or more. That is the whole arrangement, both sides.

The fix in step 3 below involves a kernel module and, in the worst case, a reboot. That is a bad thing to discover for the first time on a server that matters. If you want a disposable box to break, I spin these up on Vultr's 300 dollar trial credit: deploy the smallest AlmaLinux 10 or Rocky Linux 10 instance, run through this guide, destroy it, repeat. If you already went through the initial server setup guide on this box, you already have a sudo user and a working SSH session, which is all you need here.

Step 1: add Docker's repo

Both distros are RHEL 10 rebuilds, so Docker's rhel path is the one to use, not the centos path some older version-9 guides still point at:

$ sudo dnf install -y dnf-plugins-core
$ sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
$ dnf repolist | grep docker
docker-ce-stable   Docker CE Stable - x86_64

dnf-plugins-core is what provides config-manager; on a minimal cloud image it is not always preinstalled, and the command above is a no-op if it already is.

Step 2: install the packages

$ sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
$ docker --version
Docker version 29.7.1, build <short-sha>

The exact patch version above will not match what you see: Docker cuts new builds often, and by the time you read this it has likely moved again. That is normal, this guide does not depend on a specific patch level.

If this step fails with docker-ce-stable requires container-selinux, see "If this fails" below, it is almost always a repo problem, not a real missing dependency: container-selinux ships in AppStream and is normally already resolvable on a stock install.

Step 3: the kernel module RHEL 10 needs that version 9 did not

Enable the service now and, on a fresh AlmaLinux 10 or Rocky Linux 10 install, there is a real chance it fails:

$ sudo systemctl enable --now docker
Job for docker.service failed because the control process exited with error code.
See "systemctl status docker.service" and "journalctl -xeu docker.service" for details.
$ sudo journalctl -u docker --no-pager | tail -5
failed to start daemon: Error initializing network controller: error obtaining controller
instance: failed to register "bridge" driver: failed to add jump rules to ipv4 NAT table:
(iptables failed: iptables --wait -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER:
Warning: Extension addrtype revision 0 not supported, missing kernel module?

That error is not a Docker bug and not something specific to your install. Until recently, iptables-nft pulled in kernel-modules-extra automatically as a side effect, so the xt_addrtype module Docker needs for its NAT rules was always present even though docker-ce never actually depended on it. That automatic pull got tightened in a recent iptables update, and RHEL 10 family minimal and cloud images do not ship the package by default. The fix:

$ sudo dnf install -y kernel-modules-extra
$ sudo modprobe xt_addrtype
$ lsmod | grep xt_addrtype
xt_addrtype           16384  0

If modprobe comes back clean and lsmod shows the module, retry systemctl enable --now docker and you are done, no reboot needed. If modprobe instead fails with something like FATAL: Module xt_addrtype not found in directory /lib/modules/$(uname -r), your running kernel and the just-installed module do not match, usually because the install also pulled a newer kernel package that has not been booted into yet. A reboot is the reliable fix here, since it is the only thing that puts you on the kernel the new module was actually built for:

$ sudo reboot
$ sudo systemctl enable --now docker
$ systemctl is-active docker
active

Step 4: verify with a container that actually runs

$ sudo docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
...

That message coming back is the real confirmation. Everything up to here can look fine (service active, no errors) while the bridge network is still broken; running a container is the only step that proves the networking path actually works.

Step 5: stop typing sudo for every command

$ sudo usermod -aG docker $USER
$ newgrp docker
$ docker run hello-world
Hello from Docker!
...

newgrp picks up the new group in your current shell; a full logout and back in does the same thing if you would rather do that. Being in the docker group is root-equivalent on the host (anyone who can talk to the Docker socket can mount / into a container), so treat it the same way you treat wheel: real users only, not a shared service account.

Step 6: SELinux stays on, and container-selinux is already doing its job

container-selinux came in as a dependency back in step 2, and it is what lets SELinux keep containers confined instead of running unconfined. Leave it that way:

$ getenforce
Enforcing

The one place this bites people is bind mounts. Mount a host directory into a container without a label and you get a permission denied error inside the container even though the Linux file permissions look fine:

$ docker run -v /srv/data:/data alpine touch /data/test
touch: /data/test: Permission denied

The fix is a relabel, not a policy change. Append :Z for a directory private to one container, or :z if more than one container needs to share it:

$ docker run -v /srv/data:/data:Z alpine touch /data/test
$ ls -Z /srv/data/test
unconfined_u:object_r:container_file_t:s0:c123,c456 /srv/data/test

If you ever hit an AVC denial that :Z alone does not explain, that is a two-minute ausearch and audit2allow job, not a reason to touch setenforce. We wrote the full workflow for that in the SELinux troubleshooting guide.

Step 7: firewalld stays on too, know what it does and does not cover

Do not disable firewalld to make container networking easier, and you should not need to. What is worth knowing going in: a port you publish with docker run -p 8080:80 gets a NAT rule inserted directly by Docker, and traffic to it never passes through firewalld's input filtering the way traffic to a process bound directly to the host does. That is expected Docker behavior on every distro, not a firewalld gap and not something version 10 changed. Two practical habits cover it: bind anything that should stay local to loopback, -p 127.0.0.1:5432:5432 instead of -p 5432:5432, and for anything that genuinely needs restricting from the outside, add the rule to Docker's own DOCKER-USER iptables chain rather than to a firewalld zone, since that is the chain Docker actually consults first.

If this fails

  • "Extension addrtype revision 0 not supported, missing kernel module?" when starting the service: this is the step 3 gotcha, sudo dnf install -y kernel-modules-extra, then modprobe xt_addrtype, then a reboot only if modprobe itself reports the module is missing for your running kernel.
  • "docker-ce-stable requires container-selinux" during install: almost always a stale or partially disabled repo, not a real missing package on a stock AlmaLinux/Rocky 10 image. sudo dnf clean all && sudo dnf makecache, confirm appstream and baseos are enabled with dnf repolist, then retry.
  • "permission denied while trying to connect to the Docker daemon socket" right after step 5: the group membership has not applied to your current shell yet. Run newgrp docker or log out and back in, then retry.

Wrap up

Six steps, one real landmine, and the landmine is the useful part: if you installed Docker CE on AlmaLinux 9 or Rocky 9 before and copy-pasted the same commands onto a version 10 box, the silent dependency that used to save you is gone, and now you know exactly which package replaces it and why. SELinux and firewalld did not get in your way here either, because they were never the problem, an undocumented packaging change was. That is the pattern worth keeping: when a guide tells you to switch something off to make an error go away, it usually just has not found the real cause yet.