
You have a fresh Ubuntu or Debian VPS and want to install Docker. Search results offer apt install docker.io, the get.docker.com script and Docker's own apt repository, and they don't install the same thing: on 1 November 2026, Debian 12's own package is Docker 20.10.24 while Docker's repository serves 29.9.2. This guide follows Docker's install pages, checked that day, and covers what people trip over afterwards: sudo, Compose, starting on boot and the firewall.
Quick answer: Install Docker from Docker's official apt repository. Remove conflicting packages, add Docker's GPG key and a docker.sources file, run sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin and test with sudo docker run hello-world. On Ubuntu 22.04, 24.04, 26.04 and 26.10 and Debian 12 and 13 this installs Docker Engine 29.9.2 with the Compose plugin (as of 1 November 2026), and the Docker service starts on boot by default. Add a user to the docker group only if you'd trust them with root, and remember that ports Docker publishes skip UFW.
Which Docker Install Method to Use on a VPS
| Method | What you get (1 November 2026) | Verdict |
|---|---|---|
| Docker's apt repository | Engine 29.9.2, Compose plugin 5.6.1, updates through apt | Use this |
docker.io from Ubuntu | 29.1.3 on Ubuntu 24.04 and 26.04 | Ubuntu's build, not Docker's |
docker.io from Debian | 20.10.24 on Debian 12, 26.1.5 on Debian 13 | Old |
get.docker.com script | Docker's repository, set up without questions | Test servers only |
| Docker Desktop for Linux | A desktop app with its own VM | Not for a headless server |
Docker's install pages call the distribution packages "unofficial Docker packages, which may conflict with the official packages provided by Docker" and have you remove them first. The convenience script "isn't recommended for production environments": it installs the latest release without asking, which can mean an unexpected major upgrade. Docker Desktop for Linux runs a virtual machine and needs a desktop environment such as GNOME or KDE.
Before You Start
Check your release and architecture:
. /etc/os-release && echo "$PRETTY_NAME ($VERSION_CODENAME)"
dpkg --print-architecture
Docker supports 64-bit Ubuntu 26.10, 26.04 LTS, 24.04 LTS and 22.04 LTS, and Debian 13 (trixie) and 12 (bookworm), on amd64 and arm64 among others.
The commands use sudo. Logged in as root on Debian and sudo is missing? Run apt install sudo, or leave sudo out. On a Space-Node VPS you pick a Linux image such as Ubuntu or Debian in the order form, and the KVM server gives you full root access, so these steps work as written.
Step 1: Remove Conflicting Packages
On Ubuntu:
sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc | cut -f1)
On Debian, which has no docker-compose-v2 package:
sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-doc docker-buildx podman-docker containerd runc | cut -f1)
On a fresh server dpkg prints "no packages found matching" lines and apt removes nothing. Images, containers and volumes in /var/lib/docker stay in place.
Step 2: Add Docker's apt Repository
On Ubuntu, exactly as Docker's page has it:
# Add Docker's official GPG key:
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/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
On Debian, the URLs say debian and Suites takes the Debian codename:
# Add Docker's official GPG key:
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
# Add the repository to Apt sources:
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
Optional key check: gpg --show-keys /etc/apt/keyrings/docker.asc (install gpg if it's missing) should show "Docker Release (CE deb)" with fingerprint 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88, the key both URLs served on 1 November 2026. Then confirm apt sees the repository:
apt-cache policy docker-ce
The Candidate: line should show a version such as 5:29.9.2-1~ubuntu.24.04~noble, and the version table should list download.docker.com.
Step 3: Install Docker Engine and the Compose Plugin
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
docker-ce is the Docker daemon, docker-ce-cli the docker command, containerd.io bundles containerd and runc, docker-buildx-plugin adds docker buildx and docker-compose-plugin adds docker compose.
To pin a version, pick one from the list and name it for both Docker packages:
apt list --all-versions docker-ce
VERSION_STRING=5:29.9.2-1~ubuntu.24.04~noble
sudo apt install docker-ce=$VERSION_STRING docker-ce-cli=$VERSION_STRING containerd.io docker-buildx-plugin docker-compose-plugin
On Debian 12 the string ends in ~debian.12~bookworm, on Debian 13 in ~debian.13~trixie.
Step 4: Check That Docker Runs
sudo systemctl status docker
sudo docker run hello-world
hello-world downloads a test image, prints a message that includes "This message shows that your installation appears to be working correctly." and exits. Then check the versions and the boot setting:
sudo docker version
sudo docker compose version
systemctl is-enabled docker
Docker's post-install page says the service starts on boot by default on Debian and Ubuntu, so the last line prints enabled. If status shows Docker stopped, run sudo systemctl start docker.
Step 5: Run Docker Without sudo
Run docker ps as a normal user and you get permission denied while trying to connect to the docker API at unix:///var/run/docker.sock. The daemon's socket is open to root and the docker group, which the package already created, so add your user:
sudo usermod -aG docker $USER
Run it as the user who will use Docker (or put that user's name in place of $USER), then close the SSH session and log in again so the membership applies. Test with docker run hello-world, without sudo.
Know what this gives away. Docker's docs: "The docker group grants root-level privileges to the user." A member can start a container that mounts the host's / and change any file, which is why Docker's security page says "only trusted users should be allowed to control your Docker daemon". For a user who must not have that, look at rootless mode, where the daemon itself runs without root.
Used sudo docker before joining the group? A permission denied warning about ~/.docker/config.json can follow. Docker's fix:
sudo chown "$USER":"$USER" /home/"$USER"/.docker -R
sudo chmod g+rwx "$HOME/.docker" -R
Step 6: Start a Test Stack That Survives a Reboot
Add sudo to the docker commands if you skipped Step 5:
mkdir -p ~/docker-test && cd ~/docker-test
cat > compose.yaml <<'EOF'
services:
web:
image: nginx:1.30-alpine
restart: unless-stopped
ports:
- "127.0.0.1:8080:80"
EOF
docker compose up -d
curl -I http://127.0.0.1:8080
The first line of the reply should be HTTP/1.1 200 OK. Two lines in that file matter for every stack you run later:
restart: unless-stopped. Docker's default restart policy isno, so without it a container stays down after a reboot even though Docker itself starts. With it, Docker restarts the container when it exits or the daemon restarts, unless you stopped it yourself.127.0.0.1:8080:80. Docker's docs: with the localhost address in the publish flag, "only the Docker host can access the published container port." Without an address, Docker publishes the port on all host addresses, whatever UFW says.
docker compose down removes the test.
Step 7: Cap Container Logs
Logs from the default json-file driver grow over time, and Docker's post-install page warns they can exhaust your disk. The local driver rotates by default and keeps 100 MB per container. Make it the default (if /etc/docker/daemon.json already exists, add the key to it instead):
echo '{ "log-driver": "local" }' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
It applies to containers created after the restart. Our Docker Compose production guide sets the same per service and continues with SSL, deploys and backups.
The UFW Trap: Published Ports Skip Your Firewall
Docker's install pages warn that with ufw or firewalld, ports you publish "bypass your firewall rules". Docker routes that traffic with its own NAT rules, so it "gets diverted before it goes through the ufw firewall settings", and sudo ufw deny 5432 does nothing against a container started with -p 5432:5432. Publish internal services on 127.0.0.1 as in Step 6, or don't publish them and let containers talk over a Docker network. Our guide to why Docker bypasses UFW covers ports that must stay public and how to test from outside. Docker also only supports firewall rules made with iptables or ip6tables; rules created with nft aren't supported on a host with Docker.
Upgrade or Remove Docker Later
Docker now comes from an apt repository, so sudo apt update && sudo apt upgrade upgrades it with the rest of the system. The package restarts the Docker service, and by default a stopping daemon shuts down running containers; those set to always or unless-stopped start again. Live restore ("live-restore": true in daemon.json) keeps containers running across patch releases, but not major upgrades.
To remove Docker completely:
sudo apt purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
sudo rm -rf /var/lib/docker /var/lib/containerd
sudo rm /etc/apt/sources.list.d/docker.sources /etc/apt/keyrings/docker.asc
The second line deletes every image, container and volume, so back up first; our Docker volume backup guide covers volumes and databases.
If the Install Fails
E: Unable to locate package docker-ce or Package 'docker-ce' has no installation candidate. apt doesn't see Docker's repository. Check that /etc/apt/sources.list.d/docker.sources exists and says linux/ubuntu on Ubuntu or linux/debian on Debian, then look for an error about download.docker.com in the output of sudo apt update.
A warning that the keys in docker.asc are ignored, or NO_PUBKEY. The key file is missing or apt can't read it. Run the curl and chmod a+r lines from Step 2 again.
Conflicting values set for option Signed-By or "configured multiple times". An older guide added Docker's repository a second time, for example as a .list file. Find it with ls /etc/apt/sources.list.d/, delete the old Docker entry and keep docker.sources.
docker: unknown command: docker compose. The Compose plugin is missing: sudo apt install docker-compose-plugin.
failed to connect to the docker API at unix:///var/run/docker.sock or Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? Docker 29 prints the first when the socket file is missing and the second when nothing answers on it. Either way the daemon isn't running: start it with sudo systemctl start docker, and read sudo journalctl -u docker -n 50 --no-pager if it stops again.
FAQ
Is apt install docker.io good enough?
It installs your distribution's build, not Docker's: 29.1.3 on Ubuntu 24.04 and 26.04, but 20.10.24 on Debian 12 (checked 1 November 2026). Docker's docs call these unofficial packages that may conflict with theirs, so pick one source and never mix them. Docker's repository gives you current releases that match Docker's docs.
Can I use the get.docker.com script on a VPS?
On a test box, yes. Docker says it "isn't recommended for production environments": it installs the latest release without asking, which can bring an unexpected major upgrade. Download it with curl -fsSL https://get.docker.com -o get-docker.sh, read it, and preview with sudo sh ./get-docker.sh --dry-run. Upgrade through apt afterwards; Docker warns that running the script again can cause issues.
Do I need to install Docker Compose separately?
No. The docker-compose-plugin package from Step 3 gives you docker compose. The hyphenated docker-compose is either Compose v1, written in Python and no longer supported (Docker's docs list v2 and v5), or the standalone binary, which Docker calls legacy. Debian 12's own docker-compose package is 1.29.2, which is v1. Change old scripts to docker compose.
Do my containers start again after a reboot?
The Docker service does, by default on Ubuntu and Debian. Containers only come back with the restart policy always or unless-stopped: --restart unless-stopped with docker run, or restart: unless-stopped in Compose. For a container that already runs, docker update --restart unless-stopped <name> adds it.
Does this work on Ubuntu 26.04 and Debian 13?
Yes. On 1 November 2026 Docker's repository had Engine 29.9.2 for Ubuntu 26.04 (resolute) and Debian 13 (trixie), and the commands are the same: the Suites line fills in the codename for you.
Sources
All opened on 1 November 2026:
- Docker Engine install: Ubuntu, Debian, post-installation steps, Engine 29 release notes, docker-install script
- Docker's repository: Ubuntu suites and Debian suites with their amd64 package lists, and the signing key, checked with
gpg --show-keys - Docker packaging: docker-ce.postinst, rules, docker-ce.dirs, dh_installsystemd(1)
- Docker Compose: plugin install, install overview, history and versions
- Docker docs: packet filtering and firewalls, port publishing, start containers automatically, live restore, local logging driver, configure logging drivers, security, rootless mode, Docker Desktop for Linux
- Error messages: Docker CLI 29.9.2 docker.go, request.go, errors.go; apt cacheset.cc, private-cacheset.cc, debmetaindex.cc, contrib/gpgv.cc, methods/gpgv.cc; hello-world
- Distribution packages: docker.io for Ubuntu 24.04, Ubuntu 26.04, Debian 12, Debian 13; docker-compose for Debian 12
- nginx official image tags