How to Install Docker on Debian 13 Step by Step
Table of contents
- Key takeaways
- Why not the Debian package
- Preparing the ground
- GPG key and repository
- Installing the right packages
- What Docker Engine 29 changes on Debian 13
- Verification and the docker group
- Configuration that prevents surprises
- Problems that always show up
- How we tested this guide
- Post-install checklist: from "hello-world" to server
- Conclusion
- Frequently asked questions
- Do I need to remove docker.io before installing Docker CE on Debian 13?
- Why is being in the docker group a security risk?
- What do I do if docker run hello-world fails after installation?
- Does this guide work on Debian 12?
- Sources
Tested with Docker Engine 29.8.1 · Compose 5.5.1 · Debian 13.6 / 12.15 (arm64) · verified
Updated: 2026-09-16
Installing Docker on Debian 13 means replacing Debian's docker.io package (26.1.5) with the official repository: store the key in /etc/apt/keyrings/docker.asc, declare the repository in docker.sources, install docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin and docker-compose-plugin, then set log rotation and live-restore in daemon.json before exposing the server to production.
Installing Docker on Debian 13 looks like a mechanical errand: copy four commands and done. But hidden inside that process are decisions that shape the next twelve months of operation. Which repository to use, how to manage permissions, and what to put in daemon.json from the first boot are questions with real consequences once the machine graduates from experiment to exposed service. We reviewed this guide on September 16, 2026 against Debian 13 "Trixie" and Docker Engine 29.8.1.
Key takeaways
-
Debian 13 ships
docker.io26.1.5, while Docker released 29.8.1 on September 15, 2026: the official Docker repository is the only reasonable choice for production. -
The standard install requires five packages:
docker-ce,docker-ce-cli,containerd.io,docker-buildx-plugin, anddocker-compose-plugin. -
Membership in the
dockergroup is practically equivalent to root on the machine; evaluate rootless Docker on shared servers. -
Configure log rotation and
live-restoreindaemon.jsonfrom day one, and apply them with a service restart, not areload. -
Docker still supports Debian 12 with the same commands, although Debian 12 now only gets long-term support.
-
The
docker run hello-worldthat prints the welcome message is the beginning, not the end.
Why not the Debian package
Debian ships docker.io in its repositories, and for tinkering on a laptop that is fine. Once the machine does real work, the distribution package falls short:
-
Debian 13 packages version 26.1.5[1], three major versions behind 29.8.1.
-
Debian adapts security fixes to 26.1 (the August 13, 2026 revision[2] fixes six CVEs), but the features of versions 27 to 29 never arrive.
-
containerd (1.7.24) and runc (1.1.15) are separate Debian packages, while Docker publishes its own
containerd.io(2.3.5) next to the engine.
Docker’s official repository solves all three. The 29.8.1 package for Debian 13 reached its package directory[3] on September 15 itself, and engine, client, containerd and plugins all update from that repository. This tutorial follows the official installation guide for Debian[4] on Debian 13 "Trixie", released August 9, 2025 according to the official release page[5]. The Debian wiki’s Docker page[6] draws the same line: docker.io is Debian’s own package, docker-ce is the upstream equivalent.
The docker compose plugin also comes packaged alongside the engine, ending the historical dance between hyphenated docker-compose and space-separated docker compose.
Preparing the ground
Before adding anything new, remove the seven unofficial packages that Docker’s guide lists as conflicting:
old="docker.io docker-compose docker-doc docker-buildx podman-docker"
sudo apt remove $(dpkg --get-selections $old containerd runc | cut -f1)
dpkg --get-selections keeps only the ones you have installed; if there are none, it prints no packages found matching and APT removes nothing. This cleans the binaries without touching images or volumes in /var/lib/docker and /var/lib/containerd. With the system clean, update APT and install the two dependencies the signed repository needs:
sudo apt update
sudo apt install -y ca-certificates curl
You no longer need gnupg: Docker publishes its key as ASCII text and you store it as is, without a gpg --dearmor step.
GPG key and repository
Debian keeps third-party repository keys in /etc/apt/keyrings/, one file per repository. The old apt-key add is gone from the apt 3.0.3 package in Debian 13 (Debian 12 still has /usr/bin/apt-key), and its global key was trusted for any repository, which broke APT’s isolation.
key=/etc/apt/keyrings/docker.asc
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o $key
sudo chmod a+r $key
Declare the repository in a deb822 file, the format the Debian 13 release notes[7] use instead of deb lines in sources.list. The shell fills in the release codename and the architecture before tee writes the file:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
In our arm64 test, the file ended up with Suites: trixie and Architectures: arm64. The Signed-By: field makes the key exclusive to that repository: APT will only accept Docker signatures for packages from download.docker.com.

Installing the right packages
Docker is not a single binary but a collection of pieces. The variable only keeps the command on one line:
pkgs="docker-ce docker-ce-cli containerd.io"
sudo apt install -y $pkgs docker-buildx-plugin docker-compose-plugin
What each does, with the version APT installed on September 16, 2026:
-
docker-ce(29.8.1): thedockerddaemon listening on the Unix socket and orchestrating containers. -
docker-ce-cli(29.8.1): thedockerclient that talks to the daemon. -
containerd.io(2.3.5): the low-level runtime that launches containers, with its own runc 1.5.1. -
docker-buildx-plugin(0.37.1): multi-platform builds with BuildKit. -
docker-compose-plugin(5.5.1): the declarative orchestrator you call asdocker compose.
APT also pulls in docker-ce-rootless-extras and pigz, which docker-ce recommends, and removes Debian’s docker-cli if you came from docker.io. The package enables the docker.service, docker.socket and containerd.service units, and systemd starts the service. Check it with sudo systemctl status docker.
To pin a version, list the available ones with apt list --all-versions docker-ce and pass the full string, such as 5:29.8.1-1~debian.13~trixie, to docker-ce= and docker-ce-cli= in the same apt install.
What Docker Engine 29 changes on Debian 13
Docker Engine 29.0.0, released November 10, 2025, brought two changes you notice on a new server. The version 29 release notes[8] describe them:
-
The containerd image store is the default on fresh installs: images go to
/var/lib/containerd, while volumes stay in/var/lib/docker. In our test,docker infoshoweddriver-type: io.containerd.snapshotter.v1. -
An nftables firewall backend exists, still experimental, which you enable with the
firewall-backendoption. Without it,docker infoshowedFirewall Backend: iptables.
Debian 13’s iptables is the nf_tables variant (iptables v1.8.11 (nf_tables) in our test), and docker-ce depends on the iptables and nftables packages. The official guide warns that Docker only works with iptables-nft and iptables-legacy, and does not support rules created directly with nft. Create yours with iptables in the DOCKER-USER chain.
Verification and the docker group
Three commands confirm everything is in place. The first two only query the client; the third needs sudo because your user is not in the docker group yet:
docker --version
docker compose version
sudo docker run hello-world
On Debian 13, the first two returned:
Docker version 29.8.1, build 4a63305
Docker Compose version v5.5.1
The third pulled the image and, after the progress lines, printed:
Hello from Docker!
This message shows that your installation appears to be working correctly.
If the last one fails but the first two succeed, check sudo systemctl status docker first, because those two never touch the daemon. With the daemon running, look at DNS or the registry, not the install.
Adding your user to the docker group looks cosmetic but carries serious security implications, something the Debian wiki[6] puts bluntly: group membership is more dangerous than sudo access. Group membership is practically equivalent to root on that machine: anyone who can run docker run can mount the root filesystem inside a privileged container. On a shared server, evaluate rootless Docker[9] instead. On a personal box, the group is acceptable if you understand the trade-off.
sudo usermod -aG docker $USER
newgrp docker
newgrp applies the group to the current terminal only; for everything else, the post-installation steps[10] say to log out and back in.
Configuration that prevents surprises
The file /etc/docker/daemon.json does not exist after the install: in our test, /etc/docker was empty. Without it, the json-file driver never rotates, because its max-size option[11] defaults to -1 (unlimited). Leaving it that way is the first production mistake worth avoiding. Create the file with the two parameters that deserve to be set from day one:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"live-restore": true
}
Without log rotation, a chatty container fills the disk: the example above caps each file at 10 MB and keeps a maximum of 3 in rotation. With live-restore[12], containers keep running while the daemon is down. Docker only supports it across patch releases (29.8.0 to 29.8.1), not jumps such as 29.8 to 29.9.
Apply the changes with sudo systemctl restart docker, not reload. A reload sends SIGHUP, and the dockerd reference[13] lists a short set of options reloaded that way, which includes live-restore but not log-opts. In our test, after changing max-size and sending SIGHUP, a new container still got the old value. The logging settings also only apply to containers created after the restart.
Prometheus logo, the metrics tool you can use to monitor the Docker daemon state in production (Image: Alexander Schwartz (ahus1), Apache License 2.0, via Wikimedia Commons)
Problems that always show up
-
permission denied while trying to connect to the docker API: the group change hasn’t applied to the session.newgrp dockerfixes it. -
failed to connect to the docker API at unix:///var/run/docker.sock:dockerdisn’t running.systemctl status dockerandjournalctl -u docker -n 100reveal the cause. -
Slow or refused pulls: Docker Hub limits anonymous pulls[14] to 100 every 6 hours per IPv4 address or IPv6 /64 subnet, or DNS is failing.
docker loginwith a Personal account raises the limit to 200, and a localregistry-mirrorsentry cuts the number of pulls. -
Disk full:
docker system prune -a --volumesfrees space aggressively, including anonymous volumes: be careful.
How we tested this guide
We re-ran the steps on September 16, 2026 in privileged debian:trixie (13.6) and debian:bookworm (12.15) containers on arm64. On Debian 13 the removal block took out a docker.io 26.1.5 installed beforehand, and with dockerd started by hand, hello-world, the docker group, log rotation and live-restore all worked. Without systemd we could not test the automatic start, systemctl or journalctl, and /var/lib/containerd stayed empty, so that path comes from the documentation. We did not test amd64, Debian’s 6.12 kernel, ufw or rootless mode either.
Post-install checklist: from "hello-world" to server
The docker run hello-world message confirms that the daemon starts. It confirms nothing that matters once the machine stops being an experiment. This is the full review before exposing anything.
-
You are using the official repository, not
docker.io. Check withdocker version: the repository installs the 29 branch, and Debian 13’sdocker.iostays at 26.1.5. -
All five packages are there:
docker-ce,docker-ce-cli,containerd.io,docker-buildx-pluginanddocker-compose-plugin. Without the last one,docker compose(no hyphen) does not exist. -
You have made a conscious decision about the
dockergroup. Membership equals root on the machine. On a shared server that is a security decision, not a convenience: consider rootless Docker. -
Log rotation is configured in
daemon.jsonand you restarted the service afterwards. Without it, a chatty container fills the disk and takes everything else down with it. -
live-restoreis on if you care about containers surviving a daemon restart. -
The service starts on its own:
systemctl is-enabled docker. A server that does not recover from a reboot is not in production, it is on trial. -
You know where state lives. Volumes are in
/var/lib/docker/volumes, and with Docker 29 images are in/var/lib/containerd. Volumes belong in your backup policy, or you have no backup. -
You published the port on purpose. According to the official guide, ports that Docker publishes bypass ufw and firewalld rules, even when your firewall looks closed. Check from outside the machine, not from it.
Items 4 and 8 show no symptoms on install day, which is why they turn a correct install into an incident weeks later.
Conclusion
What separates a viable install from one that will bite you in six months is not any command in the official repo, but the decisions you make right after.
Configure log rotation from day one. Enable live-restore. Understand what the docker group implies. None of these shows up in five-minute tutorials, and all matter more than the exact order of the packages.
With the daemon running, a management interface is a reasonable next step: how to install Portainer with Docker Compose v2. If the plan is to run the server with Docker Swarm, the next step is when Docker Swarm still makes sense.
This article is also available in Spanish: Cómo instalar Docker en Debian 13 paso a paso.
Frequently asked questions
Do I need to remove docker.io before installing Docker CE on Debian 13?
Yes. Run this guide’s removal block before adding the official repository. docker-ce declares a conflict with docker.io, and containerd.io declares one with containerd and runc, so APT will not let them coexist.
Why is being in the docker group a security risk?
Because any account with access to the Docker socket can mount the root filesystem inside a privileged container, which is effectively root on the machine. On a shared server, the reasonable alternative is rootless Docker.
What do I do if docker run hello-world fails after installation?
If docker --version and docker compose version respond but hello-world fails, first confirm with sudo systemctl status docker that the daemon is active, because those two commands do not need it. With the daemon running, the problem is almost always network-related (DNS, registry access or Docker Hub’s anonymous pull limit), not the install itself.
Does this guide work on Debian 12?
Yes. Docker supports Debian 12 "Bookworm" as oldstable, and in a debian:bookworm (12.15) container these same commands installed docker-ce 5:29.8.1-1~debian.12~bookworm, because they read the codename from /etc/os-release. What changes is the calendar: Debian 12 full support ended on July 11, 2026. It now only gets long-term support (LTS) until June 30, 2028, on i386, amd64, armhf, arm64 and ppc64el, and its docker.io stays at 20.10.24.
Sources
- version 26.1.5
- August 13, 2026 revision
- package directory
- official installation guide for Debian
- official release page
- Docker page
- Debian 13 release notes
- version 29 release notes
- rootless Docker
- post-installation steps
- max-size option
- live-restore
- dockerd reference
- limits anonymous pulls
- Debian.org: Debian "Bookworm" release information