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

Difficulty: Beginner\
Tested on: Debian 12, Debian 13

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.

> **Note**
>
> On Ubuntu? Use [How to install Docker Engine on Ubuntu](/guides/install-docker-ubuntu). The repository URL and the codename variable are different.

## 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 `sudo` rights and SSH key login. A minimal Debian install may not include `sudo`; [Secure a new Linux server](/guides/secure-a-new-linux-server) and [Set up SSH keys](/guides/ssh-keys) show how to prepare the account.
- Outbound HTTPS access to `download.docker.com` and 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:

```bash
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:

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

```bash
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
```

`Suites` becomes `trixie` or `bookworm`. Confirm that apt now offers Docker's build:

```bash
apt-cache policy docker-ce
```

The `Candidate` line should point to `https://download.docker.com/linux/debian`.

## Step 3 — Install Docker Engine and the plugins

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

On Debian the service starts automatically and is enabled at boot. Check it and run the test container:

```bash
sudo systemctl status docker --no-pager
sudo docker run --rm hello-world
docker compose version
```

You should see "Hello from Docker!" followed by the Compose plugin version.

> **Tip**
>
> To install a specific Docker version instead of the latest, list the available builds with `apt list --all-versions docker-ce` and install `docker-ce=VERSION docker-ce-cli=VERSION` with the same version string.

## 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`):

```bash
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
docker run --rm hello-world
```

The package normally creates the group already, so `groupadd` may report that it exists.

> **Warning**
>
> Anyone in the `docker` group can control the Docker daemon and therefore has root-level access to the server. Only add trusted administrators. Docker's rootless mode is an option when you need stronger separation.

## 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:

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

> **Tip**
>
> If `/etc/docker/daemon.json` already exists, add these keys to it instead of replacing the whole file.

## 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:

```bash
sudo apt install ufw
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
```

Then publish app containers only on the loopback address and let a reverse proxy handle ports 80 and 443. In Compose that looks like this:

```yaml
services:
  app:
    image: nginx:stable
    ports:
      - "127.0.0.1:8080:80"
```

Set up the proxy with [Caddy](/guides/caddy-reverse-proxy), [Nginx with Certbot](/guides/nginx-reverse-proxy-certbot) or [Traefik](/guides/traefik-reverse-proxy). 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:

```bash
sudo apt update
sudo apt upgrade
docker version
```

An 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.yaml` and `.env` files,
- `/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:

```bash
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:

```bash
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 /data
```

Dump 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

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

> **Danger**
>
> The following commands permanently delete all images, containers and volumes. Back up anything you need first.

```bash
sudo rm -rf /var/lib/docker /var/lib/containerd
sudo rm /etc/apt/sources.list.d/docker.sources /etc/apt/keyrings/docker.asc
```

## Troubleshooting

### 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](/guides/docker-compose-basics).
- Serve apps over HTTPS with [Caddy as a reverse proxy](/guides/caddy-reverse-proxy).
- Manage Docker from a web UI with [Portainer](/guides/install-portainer).
- See servers suited to container workloads on the [Docker hosting](/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.

---

Source: <https://hyperdc.com/guides/tutorials/install-docker-debian>\
Updated: 2026-10-09
