LinuxcontainersTested on real hardware

Install Docker + Docker Compose on Linux

Install Docker Engine and the Compose plugin on Ubuntu, Debian, or Fedora using Docker's official repository. Adds your user to the docker group so sudo isn't required.

Distrosubuntu, debian, fedora, centos, rocky
Shellbash
Updated
Script
bash
# ── Ubuntu / Debian ──────────────────────────────────────────────────────────
# Remove old/conflicting packages
for pkg in docker.io docker-doc docker-compose docker-compose-v2 \
            podman-docker containerd runc; do
  sudo apt-get remove -y "$pkg" 2>/dev/null || true
done

# Add Docker's official GPG key and repository
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/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/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine + Compose plugin
sudo apt-get update
sudo apt-get install -y \
  docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

# Add current user to the docker group (no sudo needed for docker commands)
sudo usermod -aG docker "$USER"

docker --version
docker compose version
echo "Done. Log out and back in for group membership to take effect."

What this does

Installs Docker Engine, the Docker CLI, containerd, and the docker compose plugin (Compose V2) using Docker’s official apt repository. Using the official repo ensures you get the latest stable release and timely security updates — distro-packaged docker.io is often several versions behind.

Why this approach

Docker is the most practical way to self-host services on a homelab server. Rather than installing each service directly on the OS and managing its dependencies, libraries, and config files by hand, you run it as a container — a portable, isolated process that brings everything it needs. Services don’t conflict with each other (different services can use different versions of the same library), and updating or removing a service doesn’t leave behind scattered files across the filesystem.

The reason to install from Docker’s official repository rather than the distro-packaged version is currency. The docker.io and docker-compose packages in Ubuntu and Debian repositories are maintained by the distro, which means they lag behind upstream by months or years. Docker is actively developed — the official repo gets security fixes, new features, and updated Compose V2 in days rather than months. Installing from the official repo is a one-time slightly-longer setup that pays off for the life of the server.

Compose V2 (docker compose as a plugin) is the current standard, and the distinction from the older standalone docker-compose binary matters. Some community guides and older forum posts still use the V1 syntax with the standalone binary — it works, but the standalone binary is deprecated, won’t receive new features, and isn’t installed by this method. If you follow this playbook and then run a command from a V1 guide that uses docker-compose (with a hyphen), you’ll need to add the plugin form.

The docker group membership (added with usermod -aG docker) lets your regular user account run docker commands without sudo. This is convenient but has a real security implication: membership in the docker group is effectively equivalent to sudo access, because the Docker daemon runs as root and can mount host filesystems. Only add accounts to the docker group that you’d be comfortable giving sudo access to.

Prerequisites

  • Ubuntu 20.04+ or Debian 11+ (see below for Fedora)
  • Root or sudo access
  • Internet connectivity

For Fedora / CentOS / Rocky Linux

The apt-based script above is Ubuntu/Debian only. Use the dnf method instead:

# Remove old versions
sudo dnf remove -y docker docker-client docker-client-latest \
  docker-common docker-latest docker-latest-logrotate \
  docker-logrotate docker-engine

# Add Docker's repo
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo \
  https://download.docker.com/linux/fedora/docker-ce.repo

# Install
sudo dnf install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

# Enable and start
sudo systemctl enable --now docker

# Add user to docker group
sudo usermod -aG docker "$USER"

Verify the installation

docker run --rm hello-world

You should see: Hello from Docker!

Start Docker on boot

Docker’s systemd service is enabled automatically by the package install on Debian/Ubuntu. Verify:

sudo systemctl is-enabled docker   # should print "enabled"
sudo systemctl status docker

Useful Docker Compose commands

# Start services defined in docker-compose.yml (detached)
docker compose up -d

# View running containers
docker compose ps

# View logs
docker compose logs -f

# Stop and remove containers (keeps volumes)
docker compose down

# Stop and remove containers AND volumes
docker compose down -v

Keep Docker updated

sudo apt-get update && sudo apt-get upgrade docker-ce docker-ce-cli containerd.io

Notes

  • The docker group grants equivalent root access to the host — only add trusted users
  • The official Docker apt repository uses GPG key verification (key stored in /etc/apt/keyrings/docker.asc) — more secure than piping curl to sh
  • Compose V2 (docker compose) is the current standard; the older standalone docker-compose binary is deprecated
  • On Debian, replace ubuntu with debian in the repository URL and ensure $VERSION_CODENAME resolves correctly (e.g. trixie or bookworm)