How to Install Docker on Debian and Ubuntu (2026)

The RTM Essential Stack - Gear I Actually Use

Docker is the tool you’ll use most in any modern homelab. Almost every self-hosted service in 2026 ships as a container, and most of the tutorials on this blog assume you’ve got it installed and working. This post is the quick, reliable way to get Docker running on Debian 12, Debian 13 (trixie), Ubuntu 22.04 or Ubuntu 24.04. Pick a path and follow it, you’ll be deploying containers in under five minutes.

Which path to pick

There are two ways to install Docker on a Debian-based system in 2026. Both work. They differ in how fresh the version is and how much fiddling is involved.

  • Distro repo (`docker.io`): one apt command, fewer moving parts, ships whatever Docker version your distro blessed. Fine for hobby and homelab use where you don’t need the very latest features. Caveat: Debian’s repo does not currently include the Compose v2 plugin as a package, so you’ll drop a binary in manually. Thirty-second job.
  • Docker’s official repo: always the latest Docker Engine and Compose, one extra step to add the apt source, officially supported. Preferred for production or if you want modern Docker features like containerd snapshotter, newer build cache drivers, or the latest BuildKit.

For this post I’ll show you both. If you’re not sure which you want, start with the distro repo. You can always swap to Docker’s official repo later by removing docker.io and reinstalling.

Path 1: Distro repo (quickest)

On any current Debian or Ubuntu:

sudo apt update
sudo apt install -y docker.io ca-certificates curl
sudo systemctl enable --now docker

Docker Engine is now installed and running. The docker.io package pulls in containerd and the Docker CLI at the same time. You also get ca-certificates and curl, both of which you’ll need for the next step.

Debian and Ubuntu don’t ship the Docker Compose v2 plugin in their repos. Drop the binary into Docker’s CLI plugins directory:

sudo mkdir -p /usr/libexec/docker/cli-plugins
sudo curl -fsSL \
  https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m) \
  -o /usr/libexec/docker/cli-plugins/docker-compose
sudo chmod +x /usr/libexec/docker/cli-plugins/docker-compose

Confirm both are working:

docker --version
docker compose version

You should see something like Docker version 27.x.x and Docker Compose version v2.x.x. If both commands return a version string, you’re done.

Path 2: Docker’s official repo (latest)

For the current release straight from Docker, add their apt source first. This is more typing but gets you the newest versions with the compose plugin bundled.

Add the Docker GPG key and repo:

sudo apt update
sudo apt install -y 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

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

For Ubuntu, swap /linux/debian for /linux/ubuntu in both URLs above. Everything else is identical.

Then install Docker and all the official components:

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker

Verify:

docker --version
docker compose version
docker buildx version

Run as a non-root user

By default Docker commands require sudo. Run every command in this post with sudo and it works. That gets old fast.

Add your user to the docker group so Docker commands work without sudo:

sudo usermod -aG docker $USER
newgrp docker

Log out and back in (or run the newgrp docker above to pick up the new group without a fresh login). Test:

docker ps

No error means you’re in. No sudo needed anywhere else in this guide.

Worth being honest about the security trade-off: the docker group is effectively root-equivalent, because anyone in it can launch a privileged container that mounts the host filesystem. For a single-user homelab that’s fine. For a shared host with users you don’t trust, keep sudo in play and don’t grant the docker group.

Prove it works

The classic smoke test:

docker run --rm hello-world

Docker pulls the image, runs it, prints a friendly message, removes the container. If you see Hello from Docker!, your install is healthy.

For a more useful test, try running something that’ll stick around:

docker run -d --name testnginx -p 8080:80 nginx
curl -I http://localhost:8080/

You should see an HTTP/1.1 200 OK from the nginx container. Tidy up with docker rm -f testnginx when you’re done.

Optional: a few sensible defaults

Not strictly needed to get started, but worth knowing about.

Configure Docker’s daemon.json at /etc/docker/daemon.json for log rotation and sensible defaults:

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

Then sudo systemctl restart docker. Without this, container logs can grow unbounded and eat the disk. The rotation caps each log file at 10MB and keeps three rotations.

Enable Watchtower if you want your containers to auto-update. One container that watches the rest and pulls newer images on a schedule. Useful for homelab kit where you want latest versions without manual intervention:

docker run -d --name watchtower \
  --restart unless-stopped \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtower \
  --cleanup --schedule "0 0 4 * * *"

Runs nightly at 4am, pulls new images, restarts containers, removes old images.

When things go wrong

“Cannot connect to the Docker daemon” usually means Docker isn’t running. Check with sudo systemctl status docker. If it’s not active, sudo systemctl start docker.

“permission denied while trying to connect to the Docker daemon socket” means you’re not in the docker group (or haven’t logged out and back in since adding yourself). Run groups to check. If docker isn’t listed, newgrp docker or just log out and back in.

“docker-compose-plugin: no such package” on Debian means you used Path 1 but skipped the compose plugin binary step. Scroll back up. The distro repo does not include the plugin, you have to install it manually.

Slow image pulls on a new install are usually the default Docker Hub rate limits biting. For serious use, sign in with docker login (free Docker Hub account gives you a higher rate limit), or point at a self-hosted registry for your own images.

Where to go from here

With Docker installed you can now follow every other container-based tutorial on this blog. The usual next steps:

For the full stack I actually run, including hosting, domains, tooling and filming gear, the RTM Essential Stack has the complete list. Affiliate links, no paid placements, no nonsense.

One more thing

Docker changes less than people think. These commands work on Debian 12, Debian 13, Ubuntu 22.04 and Ubuntu 24.04 with minor tweaks, and will almost certainly still work in a year. If you’re coming back to this post after a while, the only bit likely to have aged is the Compose plugin download URL, and even that’s been stable for years.

Container runtime is infrastructure plumbing. Install it once, don’t think about it again until something breaks.

Enjoyed this guide?

New articles on Linux, homelab, cloud, and automation every 2 days. No spam, unsubscribe anytime.

Scroll to Top