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 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.io 26.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, and docker-compose-plugin.

  • Membership in the docker group is practically equivalent to root on the machine; evaluate rootless Docker on shared servers.

  • Configure log rotation and live-restore in daemon.json from day one, and apply them with a service restart, not a reload.

  • Docker still supports Debian 12 with the same commands, although Debian 12 now only gets long-term support.

  • The docker run hello-world that 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.

Bash logo, the command interpreter used to run all Docker installation steps on Debian

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): the dockerd daemon listening on the Unix socket and orchestrating containers.

  • docker-ce-cli (29.8.1): the docker client 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 as docker 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 info showed driver-type: io.containerd.snapshotter.v1.

  • An nftables firewall backend exists, still experimental, which you enable with the firewall-backend option. Without it, docker info showed Firewall 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 productionPrometheus 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 docker fixes it.

  • failed to connect to the docker API at unix:///var/run/docker.sock: dockerd isn’t running. systemctl status docker and journalctl -u docker -n 100 reveal 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 login with a Personal account raises the limit to 200, and a local registry-mirrors entry cuts the number of pulls.

  • Disk full: docker system prune -a --volumes frees 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.

  1. You are using the official repository, not docker.io. Check with docker version: the repository installs the 29 branch, and Debian 13’s docker.io stays at 26.1.5.

  2. All five packages are there: docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin and docker-compose-plugin. Without the last one, docker compose (no hyphen) does not exist.

  3. You have made a conscious decision about the docker group. Membership equals root on the machine. On a shared server that is a security decision, not a convenience: consider rootless Docker.

  4. Log rotation is configured in daemon.json and you restarted the service afterwards. Without it, a chatty container fills the disk and takes everything else down with it.

  5. live-restore is on if you care about containers surviving a daemon restart.

  6. 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.

  7. 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.

  8. 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

  1. version 26.1.5
  2. August 13, 2026 revision
  3. package directory
  4. official installation guide for Debian
  5. official release page
  6. Docker page
  7. Debian 13 release notes
  8. version 29 release notes
  9. rootless Docker
  10. post-installation steps
  11. max-size option
  12. live-restore
  13. dockerd reference
  14. limits anonymous pulls
  15. Debian.org: Debian "Bookworm" release information