How to Install Docker on Ubuntu 26.04 (Step-by-Step)

Install Docker on Ubuntu 26.04 with Docker’s official APT repository, Compose v2, non-root access, safe tests, and troubleshooting for fresh VPS deployments.
A polished 3D server rack with glowing blue container cubes and an orange accent on a midnight-blue background.

This guide shows you how to install Docker on Ubuntu 26.04 with Docker Engine, Compose v2, and a verified container in about ten minutes. The final web test listens only on the VPS itself, so you can confirm networking without accidentally publishing a service to the internet.

Prerequisites

  • A 64-bit Ubuntu Server 26.04 LTS VPS (Resolute), with at least 2 GB of RAM and 10 GB of free disk space for Docker images and containers.
  • SSH access as root, or a normal Linux account with working sudo privileges.
  • Outbound HTTPS access to download.docker.com and Docker Hub.
  • No domain is needed for installation or the local test. You will need a domain later if you put a public application behind HTTPS.
  • A VPSLake Linux VPS if you need a fresh Ubuntu server with root access.

The commands assume a normal sudo-enabled account. If you are logged in as root, remove sudo; run the user-group command in Step 6 for the account that will administer Docker.

Step 1: Confirm Ubuntu 26.04 and update the VPS

Checking the release before adding a third-party repository prevents an older Ubuntu codename from being used on a Resolute host.

grep -E '^(PRETTY_NAME|VERSION_ID|VERSION_CODENAME|UBUNTU_CODENAME)=' /etc/os-release
uname -m
sudo apt update
sudo apt full-upgrade -y

The output should identify Ubuntu 26.04 and show a supported 64-bit architecture such as x86_64 or aarch64:

PRETTY_NAME="Ubuntu 26.04 LTS"
VERSION_ID="26.04"
VERSION_CODENAME=resolute
x86_64

The exact PRETTY_NAME text can change with point releases. Resolve any DNS, mirror, or interrupted-package error before continuing.

Step 2: Remove packages that conflict with Docker Engine

Ubuntu’s docker.io package and separately installed runtimes can conflict with the containerd version bundled with Docker’s official packages.

On a new VPS, remove possible conflicting packages:

sudo apt remove -y docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc

APT may say that some packages are not installed; that is expected. This command does not automatically remove images, containers, volumes, or networks in /var/lib/docker/. On an existing Docker or Podman host, inspect workloads before removing a runtime.

Step 3: Add Docker’s signed Ubuntu repository

Docker’s repository provides the Engine, CLI, containerd, Buildx, and Compose plugin as a coordinated package set, while the keyring lets APT verify its metadata.

Install the keyring prerequisites and create a deb822 source that reads Ubuntu 26.04’s codename from the host:

sudo apt 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
sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null <<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

Check that APT can see an Engine candidate from Docker’s repository before installing it:

apt-cache policy docker-ce

The candidate should come from download.docker.com and reference the Resolute package stream:

Candidate: 5:29.x.y-1~ubuntu.26.04~resolute
 500 https://download.docker.com/linux/ubuntu resolute/stable ...

For the supported release list and repository procedure, see Docker’s Ubuntu installation documentation.

Step 4: Install Docker Engine and Compose v2

Installing the daemon and plugins together keeps the Docker client, runtime, image builder, and Compose integration compatible.

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

Confirm that systemd started Docker and that the CLI can reach the daemon:

sudo systemctl is-active docker
sudo systemctl is-enabled docker
sudo docker version --format 'Client {{.Client.Version}} / Server {{.Server.Version}}'
sudo docker compose version

Patch versions change as Docker publishes updates, but the shape of the output should be:

active
enabled
Client 29.x.y / Server 29.x.y
Docker Compose version v2.x.y

Step 5: Run Docker’s installation test

The official hello-world image checks the complete path from the CLI to the daemon, registry, image cache, container creation, and process startup.

sudo docker run --rm hello-world

Near the end of the output, look for the success message:

Hello from Docker!
Your installation appears to be working correctly.

The container exits after printing the message. The --rm flag removes its stopped container record, although the small image remains cached.

Step 6: Give one account non-root Docker access

The Docker socket is root-owned by default. Membership in the docker group removes repeated sudo prompts, but it also grants root-equivalent control over the VPS.

Run this block while logged in as the normal account that should manage containers:

sudo groupadd --force docker
sudo usermod -aG docker "$USER"

If you are currently in a root shell, replace "$USER" with the actual login name in uppercase placeholder form, such as YOUR_LINUX_USER; do not add root unless that is intentionally the account you use. Log out of SSH completely and reconnect so the new group is loaded.

Then verify access without sudo:

id -nG
docker info --format 'Server {{.ServerVersion}}'

The group list should contain docker, and the second command should print the Engine version. newgrp docker can load the group in the current shell, but a fresh SSH session avoids stale credentials.

Step 7: Test container networking on loopback

A disposable NGINX container confirms port publishing while binding only to 127.0.0.1, so the test does not require a DNS record or an inbound firewall rule.

docker run -d --name ubuntu26-docker-check --publish 127.0.0.1:18083:80 nginx:alpine
docker ps --filter name=ubuntu26-docker-check --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
curl --head --max-time 10 http://127.0.0.1:18083

You should see a running container and an HTTP success response:

NAMES                 STATUS        PORTS
ubuntu26-docker-check Up ...        127.0.0.1:18083->80/tcp
HTTP/1.1 200 OK

Remove the disposable test when the response is confirmed:

docker stop ubuntu26-docker-check
docker rm ubuntu26-docker-check

Verify Docker on Ubuntu 26.04

Run one final check as the Docker administrator to confirm boot startup, daemon communication, Compose, and local storage:

systemctl is-active docker
systemctl is-enabled docker
docker version --format 'Client {{.Client.Version}} / Server {{.Server.Version}}'
docker compose version
docker info --format 'Containers {{.Containers}} | Images {{.Images}} | Storage {{.Driver}}'

Successful output includes active, enabled, Docker client and server versions, a Compose v2 version, and commonly overlay2 as the storage driver:

active
enabled
Client 29.x.y / Server 29.x.y
Docker Compose version v2.x.y
Containers 0 | Images 2 | Storage overlay2

Troubleshooting

E: Package 'docker-ce' has no installation candidate

APT has not loaded Docker’s repository, or the source file points to a different suite. Check the release, source, and candidate, then run the repository block in Step 3 again if needed:

grep -E '^(VERSION_ID|VERSION_CODENAME|UBUNTU_CODENAME)=' /etc/os-release
grep -E '^(Types|URIs|Suites|Components|Architectures|Signed-By):' /etc/apt/sources.list.d/docker.sources
sudo apt update
apt-cache policy docker-ce

The source should use resolute, and the policy output should show a candidate from download.docker.com. Do not replace it with noble; that installs packages for Ubuntu 24.04.

NO_PUBKEY or an APT signature error

APT cannot read the key associated with the Docker source. Download the key again and ensure it is readable before retrying; do not bypass signature verification or mark the repository as trusted:

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

permission denied while trying to connect to the Docker daemon socket

The SSH session started before the account joined the docker group, or usermod targeted a different account. Reconnect, run id -nG, and retry; sudo docker info is only a temporary diagnostic while you correct the membership.

curl: (7) Failed to connect to 127.0.0.1 port 18083

The image may still be downloading, the container may have exited, or another process may already own port 18083. Inspect the container and listener:

docker ps -a --filter name=ubuntu26-docker-check
docker logs ubuntu26-docker-check
sudo ss -ltnp 'sport = :18083'

If the port is occupied, remove the failed test and repeat it with --publish 127.0.0.1:28083:80, then request http://127.0.0.1:28083. A loopback-only binding needs no public UFW rule.

Hardening

  • Keep Docker’s API on its Unix socket. Never expose an unauthenticated Docker API on TCP port 2375; remote administration requires deliberate TLS configuration and narrow source-IP rules.
  • Treat the docker group as administrative access. Use rootless Docker if you need a stronger privilege boundary than a shared root-equivalent group.
  • Keep internal services on 127.0.0.1 until they sit behind a TLS reverse proxy. For a public web application, allow only the required ports in UFW, preserve your current SSH rule, and review Docker’s DOCKER-USER chain because published container ports can bypass ordinary UFW expectations. The VPSLake UFW firewall generator can help draft a starting ruleset.
  • Ubuntu 26.04 no longer supports legacy cgroup v1. Keep the host on its current supported kernel and do not try to run a cgroup-v1-only workload on this release.
  • Monitor /var/lib/docker and container logs. Image layers and the default JSON log driver can consume disk space even when few containers are running.

FAQ

Is Docker officially supported on Ubuntu 26.04?

Yes. Docker’s current Ubuntu instructions list Ubuntu Resolute 26.04 LTS as a supported release and provide packages through Docker’s signed APT repository. The repository command in this guide reads the host codename so the source stays aligned with the installed release.

Why use Docker’s repository instead of Ubuntu’s docker.io package?

Ubuntu’s package can be useful when you want distribution-managed versions, but it is not the package path used by Docker’s official Engine instructions. Docker’s repository supplies the Engine, containerd, Buildx, and Compose plugin together, which makes the docker compose workflow predictable.

Does Docker work with UFW on Ubuntu 26.04?

UFW can still protect host services, but Docker-published ports may be inserted into packet-filtering paths that do not behave like ordinary UFW rules. Keep tests on loopback, publish only required application ports, and use Docker’s packet-filtering and firewall guidance when you need source-IP restrictions.

Why is the command docker compose instead of docker-compose?

The Compose plugin is the maintained v2 integration and is installed by docker-compose-plugin. It is invoked as a Docker subcommand, so use docker compose up -d in a project directory rather than relying on the older standalone hyphenated command.

Samrat Ghosh
Written by

Samrat Ghosh

Founder & Infrastructure Engineer

Samrat Ghosh is the founder of VPSLake, where he builds and runs the remote desktop and VPS hosting infrastructure the company is built on. He writes hands-on guides about RDP, Windows Server, VPS management and secure remote access - the practical documentation he wishes had…

Previous Article

Best CPU for Minecraft Server: Single-Core Speed Explained

Next Article

Unmetered Dedicated Server: What It Really Means

Write a Comment

Leave a Comment

Your email address will not be published. Required fields are marked *

Subscribe to our Newsletter

Subscribe to our email newsletter to get the latest posts delivered right to your email.
Pure inspiration, zero spam ✨