Docker Engine, containerd and runc: keeping the host patched
A Docker host has three pieces of software that need security updates of their own: Docker Engine (dockerd), containerd and runc. Keep all three on a maintained release line, update them with your package manager, and never let the Docker API listen on TCP port 2375.
This page is about the host. Patching what runs inside containers means rebuilding images; that is covered in Patching containers.
What runs on a Docker host
The docker command is only a client. It talks to dockerd, which asks containerd to manage containers, and containerd uses runc to actually create each container with the host kernel. A flaw in any of them can let a container or a remote user reach the host. Flaws in runc and containerd are the classic container escapes.
Check installed versions
docker version
containerd --version
runc --version
docker version prints a Client and a Server section; the Server section lists the Engine, containerd and runc versions the daemon is actually using. If it shows an older Engine than your package manager, the daemon was not restarted after the last update. To see which packages are installed and where they came from:
# Debian/Ubuntu
dpkg -l | grep -E 'docker|containerd|runc'
apt-cache policy docker-ce docker.io
# RHEL family, Fedora, SUSE
rpm -qa | grep -E 'docker|containerd|runc'
Supported versions
Docker Engine releases come from the Moby project. Its branch list marks docker-29.x as maintained until after 29’s successor (30.x) ships; 28.x and older are unmaintained and out of scope for security advisories. The latest Engine release is 29.9.2 (October 20, 2026). Moby also lists an older 25.0 branch as maintained until about December 4, 2026; that is a source branch, so only rely on it if your vendor actually ships builds from it.
| Component | Line | Status | End of life |
|---|---|---|---|
| containerd | 2.4 | Active | May 16, 2027 |
| containerd | 2.3 | LTS | April 30, 2028 |
| containerd | 2.2 | Active | November 6, 2026 |
| containerd | 2.0 | LTS (extended) | March 2027 |
| containerd | 2.1, 1.7, 1.6 | End of life | already ended |
| runc | 1.5 (latest) | bug and security fixes | no fixed date |
| runc | 1.4 (latest-1) | security and significant bug fixes | no fixed date |
| runc | 1.3 (latest-2) | high-severity security fixes only | no fixed date |
containerd 2.0’s extension through March 2027 (LTS means long-term support) is provided by two named maintainers and is aimed at Kubernetes 1.33 on Google Kubernetes Engine, so plan to move off it. containerd 1.7 reached end of life on September 30, 2026. runc ships a new minor version about every six months; each release line moves down one support tier when a new one comes out. runc 1.6.0-rc.1 appeared in October 2026, so when 1.6.0 ships, 1.3 stops getting fixes.
Distribution packages vs Docker’s repository
There are two common ways to get Docker on a server:
- Docker’s own repository (
download.docker.com): packagesdocker-ce,docker-ce-cli,containerd.io(which also contains runc),docker-buildx-pluginanddocker-compose-plugin. You get Docker’s current release soon after it ships. Docker supports Debian 13 and 12, Ubuntu 26.10, 26.04, 24.04 and 22.04, RHEL 8, 9 and 10, Fedora and a few others. - Your distribution’s packages, such as
docker.io,containerdandruncon Debian and Ubuntu, ordockeron SUSE and Alpine. The distribution backports security fixes into the version it shipped, so the version number can look old while still being patched. Check the distribution’s security tracker, not the upstream version number. RHEL’s own repositories offer Podman instead of Docker Engine.
Don’t mix the two: Docker’s install guides tell you to remove the distribution packages first, because they conflict.
Update commands
Docker’s repository (Debian and Ubuntu):
sudo apt update
sudo apt install --only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Distribution packages (Debian and Ubuntu): a normal sudo apt update && sudo apt upgrade includes Docker, containerd and runc. On current Ubuntu releases the containerd daemon is built from the containerd-app source package, so look for that name in Ubuntu notices.
Docker’s repository (RHEL, Fedora and compatible):
sudo dnf upgrade --refresh docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
SUSE (distribution packages):
sudo zypper refresh
sudo zypper update docker containerd runc
Alpine (as root; Docker is in the community repository):
apk update
apk upgrade
FreeBSD: Docker Engine needs a Linux kernel and does not run natively on FreeBSD. If you run it in a Linux virtual machine, patch it there with the commands above.
To roll out a specific version with Docker’s repository, list what is available with apt list --all-versions docker-ce (or dnf list docker-ce --showduplicates) and install that version string, as Docker’s install guides show.
Restarts and live restore
Restarts a service. Check the configuration first with sudo dockerd --validate (it reads /etc/docker/daemon.json; a broken file stops the daemon from starting). A new Engine only takes effect when dockerd restarts, and by default a daemon restart stops the running containers. Containers with a restart policy come back; others don’t. Check after the upgrade and restart it yourself if docker version still shows the old Server version:
sudo systemctl restart docker # restarts dockerd; containers stop unless live-restore is on
sudo systemctl restart containerd # after a containerd-only update
On Alpine use rc-service docker restart. To keep containers running during daemon upgrades, enable live restore in /etc/docker/daemon.json:
{
"live-restore": true
}
Then sudo systemctl reload docker (no container downtime). Docker supports live restore only for patch releases within a line (for example 29.9.1 to 29.9.2), not for upgrades between major versions, and it may fail if you skip releases. It does not cover Swarm services.
runc runs each time a container starts or you docker exec into one, so a fixed runc is used from the next start. When an advisory is about container start-up (most runc escapes are), restart or recreate containers so none were started by the old binary. A kernel update needs a reboot; see kernel updates.
Verify
docker version
docker info | grep -iE 'server version|live restore'
docker ps
Confirm the Server, containerd and runc versions match a fixed release, and that the containers you expect are running.
Never expose port 2375
Anyone who can reach the Docker API can start a privileged container that mounts the host’s disk, which means full root on the server. Port 2375 is the default for the API without TLS: no encryption and no authentication. Docker’s documentation warns that remote access can let non-root users gain root on the host and that remote access without TLS is not recommended. Binding it to localhost doesn’t help much either: every local user and process that can connect gets the same root access.
Check whether the daemon listens on TCP:
sudo ss -ltnp | grep dockerd
grep -s hosts /etc/docker/daemon.json
systemctl cat docker | grep ExecStart
If you see tcp://0.0.0.0:2375 or any other -H tcp:// without TLS, remove it and restart Docker. For remote management, use SSH instead, for example docker -H ssh://admin@server ps, which needs no open Docker port. If you really need TCP, use TLS with client certificates on port 2376 and firewall it to your admin addresses. Docker’s own warning about the client keys: “Guard these keys as you would a root password!”
Was 2375 open to the internet? Treat the host as compromised, not just misconfigured. Look for unknown containers and images (docker ps -a, docker images) and follow cryptominer cleanup and backdoor checks.
Where advisories are published
- Docker Engine (Moby): github.com/moby/moby/security/advisories, plus the Engine release notes, which name the CVEs each release fixes.
- containerd: github.com/containerd/containerd/security/advisories. Example: the critical CRI label flaw on our page for CVE-2026-53488.
- runc: github.com/opencontainers/runc/security/advisories.
- Docker’s product-wide security announcements (mostly Docker Desktop, sometimes Engine and runc).
On GitHub you can “Watch” a repository with custom notifications for security alerts. If you use distribution packages, follow your distribution’s advisories instead (see following security advisories). Current high-profile issues are on our vulnerabilities page.
Hardening tips
- Keep the API on the local Unix socket only; use SSH for remote access.
- Treat the
dockergroup as root. Docker’s documentation says it “grants root-level privileges to the user”, so add only admins. - Published ports bypass ufw and firewalld rules. Bind internal services to localhost (
-p 127.0.0.1:8080:80) and filter in front of the host. See firewall basics. - Don’t mount
/var/run/docker.sockinto containers unless you accept that the container controls the host. - Avoid
--privilegedand host mounts of/,/etcor/proc. - Consider rootless mode or user namespace remapping, so root in a container is not root on the host.
- Run only images you trust, from registries you control, and rebuild them regularly.
- Patch and reboot the host kernel on schedule; all containers share it.
Sources
- Docker Engine release notes, Docker Docs
- Branches and tags, Moby project
- Install Docker Engine, Docker Docs
- Install Docker Engine on Ubuntu, Docker Docs
- Install Docker Engine on Debian, Docker Docs
- Install Docker Engine on RHEL, Docker Docs
- Linux post-installation steps, Docker Docs
- Live restore, Docker Docs
- Configure remote access for Docker daemon, Docker Docs
- Protect the Docker daemon socket, Docker Docs
- Docker Engine security, Docker Docs
- Docker security announcements, Docker Docs
- containerd releases and support horizon, containerd
- runc release policy, Open Container Initiative
- runc releases, Open Container Initiative
- containerd security advisories, GitHub
- runc security advisories, GitHub
- Moby security advisories, GitHub
- CVE-2026-53488, Ubuntu security