How to Install Docker on Debian 12 Step by Step
Table of contents
- Key takeaways
- Why Not the Debian Package
- Preparing the Ground
- GPG Key and Repository
- Installing the Right Packages
- Verification and the docker Group
- Configuration that prevents surprises
- Problems that always show up
- Conclusion
- Frequently asked questions
- Do I need to remove docker.io before installing Docker CE on Debian 12?
- Why is being in the docker group a security risk?
- What do I do if docker run hello-world fails after installation?
- Sources
Updated: 2026-07-07
Installing Docker on Debian 12 means replacing the Debian docker.io package with the official repository: import the GPG key into /etc/apt/keyrings, install the five packages 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 12 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 very first boot are questions with real consequences once the machine graduates from experiment to exposed service.
Key takeaways
-
Debian’s
docker.iopackage trails several minors behind; 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 to avoid the most common problems. -
The
docker run hello-worldthat prints the green 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:
-
The packaged version trails Docker’s stable branch by several minors.
-
Security patches take longer to land.
-
Components (engine, CLI, containerd, BuildKit) are not updated as a coordinated set.
Docker’s official repository solves all three: you get the current version, patches arrive the day they are released, and components move together. This tutorial follows the official installation guide for Debian[1] on Debian 12 "Bookworm", released June 10, 2023 according to the official release page[2]. The Debian wiki’s Docker page[3] draws the same line: docker.io is Debian’s own package, docker-ce is the upstream equivalent. The docker compose v2 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 any previous install:
sudo apt-get remove docker docker-engine docker.io containerd runc
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 minimum dependencies for adding a signed repository:
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
GPG Key and Repository
Debian’s modern method for repository keys is to drop them into /etc/apt/keyrings/ as individual files. The old apt-key add has been deprecated for years because a globally installed key implicitly signs any repository, breaking APT’s isolation.
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg |
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg]
https://download.docker.com/linux/debian
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" |
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
The signed-by= directive 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:
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
docker-buildx-plugin docker-compose-plugin
What each does:
-
docker-ce: thedockerddaemon listening on the Unix socket and orchestrating containers. -
docker-ce-cli: thedockerclient that talks to the daemon. -
containerd.io: the low-level runtime that launches containers. -
docker-buildx-plugin: multi-platform builds with BuildKit. -
docker-compose-plugin: declarative v2 orchestrator.
After the install, systemd starts the service and leaves it enabled.
Verification and the docker Group
Three commands confirm everything is in place:
docker --version
docker compose version
docker run hello-world
If the last fails but the first two succeed, the problem is usually 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[3] 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[4] instead. On a personal box, the group is acceptable if you understand the trade-off.
sudo usermod -aG docker $USER
newgrp docker
Configuration that prevents surprises
The file /etc/docker/daemon.json is empty by default. Leaving it that way is the first production mistake almost everyone makes. 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 in days: the example above caps each file at 10 MB and keeps a maximum of 3 in rotation. With live-restore[5], containers survive a daemon restart, so Docker upgrades stop taking services down. Apply changes with sudo systemctl reload docker.
Prometheus logo, the metrics tool you can use to monitor the Docker daemon state in production
Problems that always show up
-
permission deniedwithout sudo: the group change hasn’t applied to the session.newgrp dockerfixes it. -
Cannot connect to the Docker daemon:dockerdisn’t running.systemctl status dockerandjournalctl -u docker -n 100reveal the cause. -
Slow pulls: Docker Hub limits anonymous pulls[6] to 100 every 6 hours, or DNS issues. A local
registry-mirrorsis the remedy. -
Disk full:
docker system prune -a --volumesfrees space aggressively, including anonymous volumes: be careful.
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, the natural next step is often a management interface: 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: Como instalar Docker en Debian 12 paso a paso.
Frequently asked questions
Do I need to remove docker.io before installing Docker CE on Debian 12?
Yes. Run sudo apt-get remove docker docker-engine docker.io containerd runc before adding the official repository. The two packages compete for the same socket and the same service files, so leaving them side by side causes inconsistent startups.
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 fine but hello-world fails, the problem is almost always network-related (DNS or registry access), not the package installation itself.