How to Install Docker on Debian (13, 12, 11)

Last updated Wednesday, March 4, 2026 7:25 am 15 min read

Containers solve the “works on my machine” problem by bundling an application with every dependency it needs. Docker is the runtime that most CI pipelines, hosting platforms, and orchestration tools expect, and installing Docker CE on Debian gives you the full engine, Compose V2, and Buildx, all updated directly from Docker’s official APT repository.

Docker CE is available for Debian 13 (Trixie), 12 (Bookworm), and 11 (Bullseye) through Docker’s official APT repository, with extrepo as the quickest setup path. Beyond installation, you get non-root access, log rotation, rootless mode, systemd management, troubleshooting, and clean removal.

Prepare Debian for Docker CE Installation

Before installing Docker CE, remove any conflicting packages and update your system.

Remove Previous Docker Instances

Unofficial Docker packages from Debian’s repositories or previous installations can conflict with Docker CE. Remove any existing Docker-related packages first:

for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt remove $pkg; done

APT reports which packages were removed or confirms none were installed. This also removes containerd and runc because Docker Engine bundles its own versions. Uninstalling these packages does not delete images, containers, volumes, or networks stored in /var/lib/docker/.

To start with a completely clean slate and remove all existing Docker data, you can optionally run the following commands. Skip this step if you want to preserve existing containers and images from a previous installation.

The following commands permanently delete all Docker images, containers, volumes, and networks. Back up any important data before proceeding.

sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

Update Debian System Packages

Update your system before adding the Docker repository:

sudo apt update && sudo apt upgrade

This guide uses sudo for commands that need root privileges. If your user is not in the sudoers file yet, run the commands as root or follow the guide on how to add a user to sudoers on Debian.

Import Docker CE APT Repository on Debian

Two approaches exist for adding the Docker CE repository. Both install the same packages from the same upstream source and receive the same updates.

MethodComplexityBest For
extrepo (Recommended)SimpleQuick setup, automatic GPG key management
Manual RepositoryModerateFull control, custom configurations, scripted deployments

Use only one method, not both. Both extrepo and the manual approach create .sources files with different Signed-By paths. Running both produces a Conflicting values set for option Signed-By APT error on Debian 12+ and a hard failure on Debian 13. If you switch methods later, remove the previous configuration first (see the removal section).

Method 1: Use extrepo for Docker CE Setup (Recommended)

The extrepo tool manages third-party Debian repositories in a single command, handling GPG keys, source files, and version detection automatically.

First, install extrepo if not already present:

sudo apt install extrepo

Then enable the Docker CE repository:

sudo extrepo enable docker-ce

Finally, refresh the package cache to make Docker packages available:

sudo apt update

Verify the Docker repository is configured correctly:

apt-cache policy docker-ce

Expected output shows the Docker package available from the official repository:

docker-ce:
  Installed: (none)
  Candidate: 5:29.x.x-1~debian.[version]~[codename]
     500 https://download.docker.com/linux/debian [codename]/stable amd64 Packages

The version number and codename (bullseye, bookworm, or trixie) will match your Debian release.

With extrepo managing the configuration, skip ahead to the installation section. Method 2 is only needed if you want manual control.

Method 2: Configure Repository Manually

Manual configuration is useful for scripted deployments, air-gapped systems, or any setup where you want explicit control over the GPG key and source file.

Install Docker CE Prerequisites

Install the required packages for managing HTTPS repositories, GPG keys, and version detection. The lsb-release package provides the lsb_release command used to automatically detect your Debian version during repository configuration:

sudo apt install ca-certificates curl lsb-release

Import Docker CE GPG Key

Create the keyrings directory and download the Docker GPG key:

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

Create Docker CE DEB822 Repository File

Add the Docker repository using the modern DEB822 format. This configuration automatically detects your Debian version and system architecture:

sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(lsb_release -cs)
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

The $(lsb_release -cs) variable resolves to your Debian codename (bookworm, trixie, etc.) and $(dpkg --print-architecture) detects your architecture (amd64, arm64, etc.).

Docker Firewall Behavior on Debian

Docker manipulates iptables rules directly to enable container networking, which has real security implications you should understand before going further.

Docker bypasses UFW and firewalld rules when you publish container ports. Even if your firewall blocks port 8080, running docker run -p 8080:80 nginx exposes that port to the network. Docker is also only compatible with iptables-nft and iptables-legacy. Firewall rules created with nft directly are not supported. If you need to restrict Docker port access, add rules to the DOCKER-USER iptables chain.

For production servers exposed to the internet, audit which container ports you publish. Bind services that should stay private to 127.0.0.1 instead of 0.0.0.0 (for example, -p 127.0.0.1:3306:3306 for MySQL). If you use firewalld instead of UFW, see how to install firewalld on Debian for zone-based rules, but note that Docker bypasses those rules the same way.

Install Docker CE on Debian

With the repository in place, install Docker and confirm it works.

Update APT Cache for Docker CE

Refresh your system package lists to include the newly added Docker repository:

sudo apt update

Install Docker CE Packages via APT

Install Docker CE, the CLI, containerd, Buildx for multi-platform builds, and Compose V2:

sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Then, verify the installed version:

docker --version

The expected output shows the Docker CE version:

Docker version 29.x.x, build xxxxxxx

Version numbers change with each release. Anything 24.0 or newer covers everything in this article.

Verify Docker CE Installation on Debian

Finally, test your Docker installation by running the hello-world container:

sudo docker run hello-world

This pulls a test image, runs it, and prints a confirmation message:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete
Digest: sha256:d211f485f2dd1dee407a80973c8f129f00d54604d2c90732e8e320e5038a0348
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

Configure Docker for Non-Root User

By default, Docker requires root privileges because the daemon binds to a Unix socket owned by root. However, you can add your user account to the docker group to run Docker commands without sudo:

The docker group grants root-equivalent privileges. Docker allows containers to mount any host directory, meaning a user in the docker group can start a container with -v /:/host and gain unrestricted access to the entire filesystem. Only add trusted users to this group. For true privilege isolation without root-equivalent access, use Docker rootless mode instead.

sudo usermod -aG docker $USER

Afterward, log out and log back in for group membership changes to take effect. Alternatively, you can activate the new group membership in your current session:

newgrp docker

Then, verify your user can run Docker commands without sudo:

docker run hello-world

If successful, you will see the Docker welcome message without any permission errors. This confirms that your user has proper Docker access.

Manage Docker Service on Debian

Docker installs a systemd service that starts automatically. Use these commands to manage the Docker service:

Check Docker Service Status

Verify the Docker service is running:

systemctl status docker.service

Active output looks like this:

● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; preset: enabled)
     Active: active (running) since Tue 2025-11-26 10:15:32 UTC; 5min ago
       Docs: https://docs.docker.com
   Main PID: 1234 (dockerd)
      Tasks: 8
     Memory: 45.2M
        CPU: 523ms

Start, Stop, and Restart Docker Service

Manually start the Docker service (only needed if disabled or stopped):

systemctl start docker.service

Stop the Docker service:

systemctl stop docker.service

Restart to apply configuration changes:

systemctl restart docker.service

Enable or Disable Docker Service on Boot

Docker starts on boot by default after installation. To change that:

Enable Docker and containerd at boot:

sudo systemctl enable docker.service containerd.service

Disable automatic startup (useful for development machines or rootless mode):

sudo systemctl disable docker.service containerd.service

Configure Docker on Debian

These settings let you tune Docker’s defaults after the initial install. If you plan to reverse-proxy Docker containers behind Nginx on Debian, configure log rotation and user access now so logs stay manageable and deployments do not require root.

Configure Log Rotation

Docker’s default json-file log driver can grow indefinitely and eat your disk. Enable log rotation by creating or editing /etc/docker/daemon.json:

sudo nano /etc/docker/daemon.json

Add log rotation configuration:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

This configuration limits each container log to 10MB with a maximum of 3 rotated files. Then, restart Docker to apply the changes:

sudo systemctl restart docker.service

Configure User Permissions for Docker

For additional users who need Docker access, repeat the usermod command with their username:

sudo usermod -aG docker username

Replace username with the actual account name. The user must log out and back in for changes to take effect.

Use Docker Compose V2 on Debian

The installation bundles Docker Compose V2 as a CLI plugin. Run it with docker compose (space, not a hyphen):

docker compose version

Expected output confirms the Compose plugin version:

Docker Compose version v2.x.x

Compose V2 replaces the standalone docker-compose binary (V1) and is backward-compatible with most docker-compose.yml files.

Docker Command Quick Reference for Debian

The table below covers the commands you will use most when working with Docker containers, images, and resources.

CommandPurposeExample
docker runCreate and start a containerdocker run -it debian:latest /bin/bash
docker psList running containers (-a for all)docker ps -a
docker imagesList downloaded imagesdocker images
docker buildBuild an image from a Dockerfiledocker build -t myimage:latest .
docker stopGracefully stop a running containerdocker stop container_id
docker rmRemove a stopped containerdocker rm container_id
docker rmiDelete an imagedocker rmi image_id
docker network createCreate a user-defined networkdocker network create mynetwork
docker volume createCreate a named volumedocker volume create myvolume
docker system pruneRemove unused containers, images, and networksdocker system prune -f
docker commitSave container changes as a new imagedocker commit mycontainer myimage:latest

Practical Docker Workflow Example

A typical workflow starts a container, makes changes, and saves the result as a reusable image. For Dockerfile-based builds that clone repositories, make sure Git is installed on Debian on the host or inside the build context.

docker run -it --name mycontainer debian:latest /bin/bash

After installing packages or editing files inside the container, exit the shell and commit the changes:

docker commit mycontainer myimage:latest

The docker commit command only saves filesystem changes. Networking and volume configurations are managed separately with docker network and docker volume.

Troubleshoot Common Docker Issues on Debian

Common problems and their fixes:

Permission Denied Error

If Docker commands fail with a socket permission error:

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock

This error occurs when your user account is not in the docker group. First, verify group membership:

groups

If the output does not include docker, then add your user to the group and activate it:

sudo usermod -aG docker $USER
newgrp docker

Finally, verify the fix worked by running a test container:

docker run hello-world

Docker Config Permission Error

If you see a permission error about the Docker config file after adding your user to the docker group:

WARNING: Error loading config file: /home/user/.docker/config.json - stat /home/user/.docker/config.json: permission denied

This error occurs when Docker commands were previously run with sudo, creating the directory with incorrect ownership. To fix the permissions:

sudo chown "$USER":"$USER" /home/"$USER"/.docker -R
sudo chmod g+rwx "$HOME/.docker" -R

Alternatively, you can remove the ~/.docker directory (Docker recreates it automatically, but custom settings will be lost).

Docker Service Not Starting

If Docker fails to start, check the service logs for specific error details:

sudo journalctl -xeu docker.service

A common error from invalid /etc/docker/daemon.json syntax looks like:

unable to configure the Docker daemon with file /etc/docker/daemon.json: invalid character '}' after object key

Validate the JSON syntax if you have custom configuration:

cat /etc/docker/daemon.json | python3 -m json.tool

After fixing any errors, restart Docker and verify it is running:

sudo systemctl restart docker.service
systemctl status docker.service

Repository GPG Key Errors

If APT reports GPG signature verification failures during updates, re-download the Docker GPG key:

sudo rm /etc/apt/keyrings/docker.asc
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo apt update

Conflicting Signed-By Values Error

If you enabled Docker through both extrepo and the manual method, APT fails with:

E: Conflicting values set for option Signed-By regarding source
https://download.docker.com/linux/debian

Both methods create .sources files pointing to the same repository but referencing different GPG key paths. Remove whichever method you do not want to keep:

# Remove extrepo config (keep manual)
sudo rm -f /etc/apt/sources.list.d/extrepo_docker-ce.sources

# OR remove manual config (keep extrepo)
sudo rm -f /etc/apt/sources.list.d/docker.sources
sudo rm -f /etc/apt/keyrings/docker.asc

Then refresh the package cache:

sudo apt update

Container DNS Resolution Fails

If containers cannot access the internet and show “Temporary failure in name resolution” when running apt update:

Err:1 http://deb.debian.org/debian bookworm InRelease
  Temporary failure resolving 'deb.debian.org'

First, test container network connectivity by pinging an external IP and checking DNS resolution:

docker run --rm alpine ping -c 3 8.8.8.8
docker run --rm alpine nslookup google.com

If ping succeeds but DNS fails, Docker’s embedded DNS resolver may have issues. In this case, configure Docker to use a specific DNS server by editing /etc/docker/daemon.json:

{
  "dns": ["8.8.8.8", "8.8.4.4"]
}

Then, restart Docker to apply the DNS configuration:

sudo systemctl restart docker.service

Network Bridge IP Conflicts

Docker creates bridge networks that may conflict with your local network subnets. First, check existing Docker networks:

docker network ls
ip addr show | grep "br-"

If Docker bridge networks overlap with your LAN subnet (commonly 172.17.0.0/16 or 172.18.0.0/16), then configure a different default address pool in /etc/docker/daemon.json:

{
  "default-address-pools": [
    {"base": "10.200.0.0/16", "size": 24}
  ]
}

Finally, restart Docker and prune unused networks to apply the new address pool:

sudo systemctl restart docker.service
docker network prune

Reset Docker Installation

If Docker behaves unexpectedly after a failed installation or upgrade, a clean reset of the Docker data directory often resolves persistent issues.

The following commands remove all Docker images, containers, volumes, and networks. Back up any important container data before proceeding.

First, stop Docker before removing the data:

sudo systemctl stop docker.service docker.socket
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
sudo systemctl start docker.service

Docker recreates the directory structure on startup.

Afterward, verify Docker is running correctly after the reset:

docker run --rm hello-world

Docker Rootless Mode on Debian

Rootless mode runs the Docker daemon and containers without root privileges, eliminating the security risks of the docker group. Even if an attacker compromises a container, they cannot gain root access to the host. For remote Docker management over SSH, make sure SSH is enabled on Debian first.

Prerequisites for Rootless Mode

First, install the uidmap package and verify your user has subordinate UID/GID ranges configured:

sudo apt install uidmap

Then, verify your user has at least 65,536 subordinate UIDs and GIDs allocated:

grep "^$(whoami):" /etc/subuid /etc/subgid

Expected output shows allocated ranges:

/etc/subuid:username:100000:65536
/etc/subgid:username:100000:65536

Install Rootless Docker

If the system-wide Docker daemon is running, consider disabling it before setting up rootless mode:

sudo systemctl disable --now docker.service docker.socket

Next, install the rootless extras package:

sudo apt install docker-ce-rootless-extras

Then, run the rootless setup script as your non-root user:

dockerd-rootless-setuptool.sh install

Add the environment variable to your shell configuration to use rootless Docker by default:

echo 'export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock' >> ~/.bashrc
source ~/.bashrc

Finally, verify rootless mode is active by checking for the “rootless” security option:

docker info | grep -i rootless

Expected output confirms rootless operation:

 rootless

Rootless mode has limitations: it cannot bind to privileged ports below 1024 without additional configuration, overlay network performance may be reduced, and some storage drivers are not available. For most development and testing workloads, these limitations are acceptable trade-offs for improved security.

Upgrade Docker CE on Debian

Docker packages from the official repository receive automatic updates through APT. However, to manually upgrade to the latest version:

sudo apt update
sudo apt install --only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Then, verify the new version after upgrading:

docker --version

Uninstall Docker CE from Debian

To completely remove Docker CE from your Debian system, you must uninstall the packages, remove data directories, and clean up repository configuration.

Remove Docker Packages

First, uninstall all Docker-related packages and clean up orphaned dependencies:

sudo apt purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
sudo apt autoremove

The apt autoremove command cleans up packages that were automatically installed as dependencies but are no longer required after removing Docker.

Remove Docker Data

Next, delete all images, containers, volumes, and configuration data. This step is optional if you plan to reinstall Docker and want to preserve your existing containers and images.

The following commands permanently delete all Docker images, containers, volumes, and networks. Back up any important data before proceeding.

sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

Remove Repository Configuration

Finally, remove the Docker repository configuration. The cleanup commands depend on which installation method you used. For manual repository configuration:

sudo rm -f /etc/apt/sources.list.d/docker.sources
sudo rm -f /etc/apt/keyrings/docker.asc
sudo rm -f /etc/docker/daemon.json

If you installed Docker using extrepo, disable the repository with the following command. This adds an Enabled: no directive to the repository file rather than deleting it, allowing easy re-enablement later:

sudo extrepo disable docker-ce
sudo rm -f /etc/docker/daemon.json

To completely remove the extrepo configuration file instead of just disabling it:

sudo rm -f /etc/apt/sources.list.d/extrepo_docker-ce.sources
sudo rm -f /etc/docker/daemon.json

After removing the repository files, refresh the package cache to prevent stale repository information:

sudo apt update

Verify Docker Removal

Confirm Docker has been completely removed by checking package availability:

apt-cache policy docker-ce

Expected output confirms the package is no longer available:

N: Unable to locate package docker-ce

This output confirms the Docker repository has been removed and packages are no longer indexed.

Frequently Asked Questions

What is the difference between Docker CE and the docker.io package in Debian?

The docker.io package in Debian’s default repositories is a repackaged, older version maintained by Debian developers. Docker CE (Community Edition) comes directly from Docker’s official repository and receives more frequent updates, newer features, and same-day security patches. Most Docker documentation and third-party tools assume Docker CE.

Does Docker work on Debian 13 (Trixie)?

Yes. Docker CE officially supports Debian 13 (Trixie). Both the extrepo method and the manual DEB822 repository method work on Debian 13 with no extra configuration.

Is Docker Compose installed separately on Debian?

No. Docker Compose V2 is included as a plugin when you install the docker-compose-plugin package alongside Docker CE. Use it with the docker compose command (with a space). The older standalone docker-compose binary (V1) is deprecated.

Why does Docker bypass UFW and firewalld rules?

Docker manipulates iptables directly to route traffic to containers. When you publish a port with -p, Docker adds its own iptables rules that take precedence over UFW or firewalld. To restrict access, add rules to the DOCKER-USER iptables chain or bind published ports to 127.0.0.1 instead of 0.0.0.0.

Can I install Docker Desktop on Debian?

Docker Desktop is available for Debian as a .deb package from Docker’s website. However, Docker Desktop is a GUI application designed for local development, bundles its own VM, and has license restrictions for larger organizations. For servers and headless systems, Docker CE (covered in this guide) is the standard choice.

Conclusion

Docker CE is running on Debian with repository-based updates, non-root access, and log rotation configured. For stronger isolation, rootless mode removes root-equivalent access entirely. Secure containerized services behind Nginx with Let’s Encrypt on Debian, protect exposed ports with UFW on Debian, guard against brute-force attacks using Fail2ban on Debian, and manage remote access through SSH on Debian.

Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffee Buy me a coffee

Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Leave a Comment

We read and reply to every comment - let us know how we can help or improve this guide.

Let us know you are human: