How to install Docker Engine on Debian 12 and 13
Install Docker Engine with the Buildx and Compose plugins on Debian 13 Trixie or Debian 12 Bookworm from Docker's official apt repository, then secure it.
- Beginner
- 15 min read
- Updated
Tested on: Debian 12, Debian 13
This guide is not available in your language yet, so it is shown in English.
On this page
- Prerequisites
- Step 1 — Remove conflicting packages
- Step 2 — Add Docker's apt repository
- Step 3 — Install Docker Engine and the plugins
- Step 4 — Run Docker without sudo (optional)
- Step 5 — Turn on log rotation
- Step 6 — Keep published ports behind your firewall
- Update Docker
- Back up and restore
- Uninstall Docker
- Troubleshooting
- sudo: command not found
- Package 'docker-ce' has no installation candidate
- permission denied while trying to connect to the Docker daemon socket
- Containers have no network access after changing firewall rules
- The disk is filling up
- Next steps
Docker Engine is the container runtime behind most of the self-hosted apps and AI tools in this library. On Debian, the cleanest way to get a current Docker with the Buildx and Compose plugins is Docker's own apt repository. This guide sets it up on Debian 13 (Trixie) or Debian 12 (Bookworm), then covers running Docker without sudo, log rotation, the firewall caveat for published ports, updates, backups and common errors.
Prerequisites
- A server running Debian 13 (Trixie) or Debian 12 (Bookworm). Docker publishes Debian packages for amd64, arm64, armhf and ppc64le.
- A non-root user with
sudorights and SSH key login. A minimal Debian install may not includesudo; Secure a new Linux server and Set up SSH keys show how to prepare the account. - Outbound HTTPS access to
download.docker.comand to the registries you will pull images from.
Docker's documentation does not give a minimum CPU or memory size for Docker Engine; the daemon itself is small. Size the server for the containers you plan to run, using the requirements in each app guide, and keep at least 20% of the disk free for images, logs and volumes under /var/lib/docker.
Step 1 — Remove conflicting packages
Debian's archive contains Docker-related packages that conflict with Docker Engine. Remove any that are installed:
sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-doc docker-buildx podman-docker containerd runc | cut -f1)If nothing is installed, dpkg prints "no packages found" warnings and there is nothing to remove. Images, containers and volumes already in /var/lib/docker are kept.
Step 2 — Add Docker's apt repository
Install the tools for fetching the signing key, save Docker's GPG key and add the repository in deb822 format:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.ascsudo 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 updateSuites becomes trixie or bookworm. Confirm that apt now offers Docker's build:
apt-cache policy docker-ceThe Candidate line should point to https://download.docker.com/linux/debian.
Step 3 — Install Docker Engine and the plugins
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginOn Debian the service starts automatically and is enabled at boot. Check it and run the test container:
sudo systemctl status docker --no-pager
sudo docker run --rm hello-world
docker compose versionYou should see "Hello from Docker!" followed by the Compose plugin version.
Step 4 — Run Docker without sudo (optional)
Add your admin user to the docker group, then start a new login session (or run newgrp docker):
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
docker run --rm hello-worldThe package normally creates the group already, so groupadd may report that it exists.
Step 5 — Turn on log rotation
With the default json-file driver, container logs grow without limit. Switch new containers to the local driver, which rotates and compresses logs:
sudo tee /etc/docker/daemon.json <<'EOF'
{
"log-driver": "local",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
EOF
sudo systemctl restart docker
docker info | grep -i "logging driver"The output should read Logging Driver: local. Containers created before the change keep their old settings until you recreate them, for example with docker compose up -d --force-recreate.
Step 6 — Keep published ports behind your firewall
A port published without a host address (-p 8080:80) listens on every address of the server. Docker documents that ufw and firewalld rules do not filter these ports, because Docker processes the traffic before those rules apply. Debian does not install a firewall front end by default, so install ufw first:
sudo apt install ufw
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verboseThen publish app containers only on the loopback address and let a reverse proxy handle ports 80 and 443. In Compose that looks like this:
services:
app:
image: nginx:stable
ports:
- "127.0.0.1:8080:80"Set up the proxy with Caddy, Nginx with Certbot or Traefik. From another computer, nc -vz your-server-ip 8080 should now fail to connect.
Update Docker
Docker packages update together with the rest of the system:
sudo apt update
sudo apt upgrade
docker versionAn upgrade of docker-ce restarts the daemon. Containers with a restart policy such as unless-stopped come back automatically; containers without one stay stopped until you start them. Debian's unattended-upgrades, if you use it, applies Debian security updates by default and does not include Docker's repository, so schedule Docker upgrades yourself.
Updating the apps inside containers is a separate task: pull the new image and recreate the container, as each app guide explains.
Back up and restore
Back up the state, not the images (images can be pulled again):
- named volumes in
/var/lib/docker/volumes/, - host directories you bind-mount into containers,
compose.yamland.envfiles,/etc/docker/daemon.json.
To archive a named volume, stop the containers that write to it and run a short-lived container that packs the volume into the current directory:
docker run --rm -v app_data:/data -v "$(pwd)":/backup debian:stable-slim tar czf /backup/app_data.tar.gz -C /data .To restore, create the volume and unpack the archive into it:
docker volume create app_data
docker run --rm -v app_data:/data -v "$(pwd)":/backup debian:stable-slim tar xzf /backup/app_data.tar.gz -C /dataDump databases with their own tools (pg_dump, mariadb-dump) through docker exec rather than copying live database files, and keep a copy of every backup off the server.
Uninstall Docker
sudo apt purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extrassudo rm -rf /var/lib/docker /var/lib/containerd
sudo rm /etc/apt/sources.list.d/docker.sources /etc/apt/keyrings/docker.ascTroubleshooting
sudo: command not found
The server was installed with a root password and without sudo. Log in as root, run apt install sudo, add your user with usermod -aG sudo youruser, and log in again as that user.
Package 'docker-ce' has no installation candidate
apt is not reading Docker's repository. Run cat /etc/apt/sources.list.d/docker.sources and check that Suites shows trixie or bookworm and that the URI contains /linux/debian (not /linux/ubuntu). Then run sudo apt update and look for NO_PUBKEY or 404 errors.
permission denied while trying to connect to the Docker daemon socket
Your session does not have the docker group yet. Check with id; if docker is missing, repeat Step 4 and log in again, or use sudo docker meanwhile.
Containers have no network access after changing firewall rules
Flushing the ruleset (nft flush ruleset or iptables -F) also removes Docker's rules. Restart Docker with sudo systemctl restart docker to recreate them, and add your own filtering to the DOCKER-USER chain instead of flushing tables.
The disk is filling up
Run docker system df to see what uses the space. docker system prune removes stopped containers, unused networks, dangling images and build cache; docker system prune -a also removes images that no container uses. Leave --volumes out unless you are certain no volume holds data you need, and turn on log rotation (Step 5).
Next steps
- Write your first multi-container app with Docker Compose basics.
- Serve apps over HTTPS with Caddy as a reverse proxy.
- Manage Docker from a web UI with Portainer.
- See servers suited to container workloads on the Docker hosting page.
Frequently asked questions
Is Debian's docker.io package good enough?
It works, but Docker lists docker.io, docker-compose, docker-doc and podman-docker as unofficial packages that conflict with Docker Engine. Docker's own docker-ce packages follow Docker's releases and ship the Compose and Buildx plugins that most app guides use.
Which Debian releases does Docker support?
Docker currently publishes packages for Debian 13 (Trixie, stable) and Debian 12 (Bookworm, oldstable) on amd64, arm64, armhf and ppc64le. Older releases no longer receive new Docker versions.
Can I use these steps on a Debian derivative?
Docker documents Debian itself. For a derivative such as Kali Linux, Docker says to replace the codename in the repository line with the matching Debian release, for example trixie. Other derivatives may need their own instructions.
Debian 13 uses nftables. Does Docker still work?
Yes. Debian's iptables command uses the nftables backend (iptables-nft), which Docker supports. Rules you write directly with the nft command are not managed by Docker, so put your own container filtering rules in the DOCKER-USER chain with iptables.
Do I need to reboot after installing Docker?
No. The docker service starts as soon as the package is installed and is enabled at boot. You only need to log out and back in after adding your user to the docker group.