How to Install Docker on Ubuntu 26.04 LTS

Install Docker Engine, Buildx and Compose on Ubuntu 26.04 LTS, then secure, test, update and troubleshoot a production-ready container server.

Deploy a Cloud VPSCompare VPS Plans
HYEHOST mascot installing Docker Engine and Docker Compose on an Ubuntu 26.04 server

Docker turns applications and their dependencies into portable containers that can run consistently across development machines, virtual private servers and production infrastructure. On Ubuntu 26.04 LTS, the recommended installation method is to use Docker's official APT repository rather than Ubuntu's older docker.io package or the convenience installation script.

This guide installs:

  • Docker Engine.
  • The Docker command-line interface.
  • containerd.
  • Docker Buildx.
  • The current Docker Compose plugin.

It also covers non-root access, firewall behaviour, automatic startup, a working Compose deployment, safe updates and the errors most people encounter after installation.

Ubuntu 26.04 LTS, codenamed Resolute Raccoon, was released on 23 April 2026 and receives standard security maintenance until April 2031. Docker officially supports Ubuntu 26.04 LTS, making it a sensible base for a new long-lived container server.

Before You Start

You need:

  • An Ubuntu 26.04 LTS server.
  • A user with sudo access.
  • An SSH connection or web console.
  • At least 1 GB of RAM for very small containers, although 2 GB or more is more practical.
  • Enough disk space for the operating system, images, container layers, logs and persistent data.

Connect to the server:

ssh your-user@your-server-ip

Replace your-user and your-server-ip with the account and address for your server.

If this is a new VPS, update it before installing Docker:

sudo apt update
sudo apt full-upgrade -y

Check whether a reboot is required:

test -f /var/run/reboot-required && cat /var/run/reboot-required

If the command reports that a reboot is required, restart now:

sudo reboot

Reconnect after the server comes back online.

Step 1: Remove Conflicting Docker Packages

Ubuntu may already have distribution-provided Docker or container packages installed. Docker recommends removing packages that can conflict with the official Docker Engine packages.

The following command removes known conflicts if they exist:

for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do
  sudo apt remove -y "$pkg"
done

It is normal for APT to say that some of these packages are not installed.

Removing a package does not automatically delete existing Docker data under /var/lib/docker or /var/lib/containerd. If this server previously ran containers, back up important volumes and inspect that data before deleting anything.

Step 2: Add Docker's Official APT Repository

Install the packages needed to download and verify the repository:

sudo apt update
sudo apt install -y ca-certificates curl

Create the APT keyring directory:

sudo install -m 0755 -d /etc/apt/keyrings

Download Docker's signing key:

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 official stable repository:

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

Refresh APT again:

sudo apt update

Confirm that APT sees Docker's repository:

apt-cache policy docker-ce

The candidate package should come from download.docker.com, not only Ubuntu's archive.

Step 3: Install Docker Engine and Docker Compose

Install Docker Engine, the CLI, containerd, Buildx and the Compose plugin:

sudo apt install -y \
  docker-ce \
  docker-ce-cli \
  containerd.io \
  docker-buildx-plugin \
  docker-compose-plugin

The Compose plugin provides the modern command:

docker compose

Older guides may use docker-compose with a hyphen. That standalone version is now considered legacy. Use docker compose for new deployments.

Step 4: Verify the Installation

Check the Docker service:

sudo systemctl status docker --no-pager

It should show active (running). Docker normally starts automatically after installation. You can explicitly enable Docker and containerd at boot:

sudo systemctl enable docker.service containerd.service

Check the installed versions:

sudo docker version
sudo docker compose version
sudo docker buildx version

Run Docker's test container:

sudo docker run --rm hello-world

Docker will download the small test image, create a container and print a success message. The --rm option removes the stopped test container afterwards.

Step 5: Run Docker Without sudo (Optional)

By default, Docker's Unix socket is owned by root. You can add your normal account to the docker group:

sudo usermod -aG docker "$USER"

Log out and sign back in for the group change to apply:

exit

After reconnecting, verify it:

docker run --rm hello-world

Important Docker group security warning

Membership of the docker group effectively grants root-level control of the server. A user who can start unrestricted containers can mount host filesystems and access sensitive host data.

Only add trusted administrators to this group. Do not add application users or shared hosting accounts simply to avoid typing sudo.

For a stricter setup, keep Docker root-owned or evaluate Docker's rootless mode. Rootless mode reduces the privileges held by the Docker daemon and containers, but it has networking, storage and compatibility differences that should be tested against your workload.

Step 6: Understand Docker and Firewall Rules

This is the most commonly missed security detail in a new Docker installation.

When Docker publishes a container port, it creates its own firewall rules. Published ports can bypass rules you expected UFW or firewalld to enforce. Docker documents this behaviour explicitly.

For example:

ports:
  - "5432:5432"

can expose PostgreSQL on every host interface. A database should rarely be published directly to the internet.

Use one of these safer patterns:

Bind a service to localhost

ports:
  - "127.0.0.1:5432:5432"

Only applications on the server can reach that published port.

Do not publish internal services

Containers in the same Compose project can communicate using the service name. A web application can connect to db:5432 without publishing the database port on the host.

Filter forwarded Docker traffic

If you need network-level filtering before Docker accepts forwarded traffic, place suitable rules in the DOCKER-USER chain. Test changes from a second SSH session so an incorrect firewall rule does not lock you out.

For most web deployments:

  • Publish only ports 80 and 443 through a reverse proxy.
  • Keep databases, Redis, queues and admin interfaces on internal container networks.
  • Bind management ports to 127.0.0.1.
  • Restrict SSH at the host firewall or provider firewall.
  • Check the actual listening sockets after every deployment.

List listening TCP and UDP ports:

sudo ss -lntup

List Docker's published ports:

docker ps --format 'table {{.Names}}	{{.Ports}}'

Step 7: Deploy a Test Website with Docker Compose

Create a project directory:

mkdir -p ~/docker/nginx-demo
cd ~/docker/nginx-demo

Create compose.yaml:

nano compose.yaml

Add:

services:
  web:
    image: nginx:alpine
    container_name: nginx-demo
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro

Create the website:

mkdir -p html
cat > html/index.html <<'EOF'
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Docker on Ubuntu 26.04</title>
  </head>
  <body>
    <h1>Docker is working</h1>
    <p>This page is being served from an Nginx container.</p>
  </body>
</html>
EOF

Validate the Compose file:

docker compose config

Start the service:

docker compose up -d

Check its state:

docker compose ps

Test it locally:

curl http://127.0.0.1/

If port 80 is allowed through your firewall, visit:

http://your-server-ip/

View logs:

docker compose logs -f --tail=100

Press Ctrl+C to stop following the logs. This does not stop the container.

The restart: unless-stopped policy makes Docker restart the web container after a daemon or server restart unless an administrator deliberately stopped it.

To remove this example:

docker compose down

The local html directory remains because it is stored outside the container.

A Better Production Compose Layout

A real application commonly uses separate services and an internal network:

services:
  app:
    image: ghcr.io/example/my-app:1.0.0
    restart: unless-stopped
    environment:
      DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/app
    depends_on:
      db:
        condition: service_healthy
    networks:
      - internal
      - proxy

  db:
    image: postgres:18-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: app
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d app"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - internal

networks:
  internal:
    internal: true
  proxy:

volumes:
  postgres_data:

Notice that PostgreSQL has no ports section. The application reaches it over the private Compose network, but it is not published on the server's public address.

Store secrets outside compose.yaml. For a simple deployment, create a .env file and restrict it:

umask 077
printf 'DB_PASSWORD=%s
' 'replace-with-a-long-random-password' > .env
chmod 600 .env

Do not commit .env to Git. For larger environments, use a dedicated secrets manager rather than long-lived plaintext environment files.

How to Update Docker on Ubuntu 26.04

Docker packages installed from the official repository are updated through APT:

sudo apt update
sudo apt upgrade

Check available Docker versions:

apt list --upgradable 2>/dev/null | grep -E 'docker|containerd'

An Engine update may restart Docker. Schedule updates for production systems and confirm that containers return:

docker ps
docker compose ls

Container images are updated separately. From a Compose project:

docker compose pull
docker compose up -d

Pin important production images to a specific version rather than using latest. A controlled version such as nginx:1.28-alpine makes upgrades intentional and rollbacks clearer.

Inspect unused Docker data:

docker system df

Remove unused images cautiously:

docker image prune

Avoid blindly running docker system prune --all --volumes. It can remove images needed for rollback and unused volumes that still contain valuable data.

Back Up Docker Properly

A container image is not a backup. Important data usually lives in:

  • Named Docker volumes.
  • Bind-mounted directories.
  • Databases.
  • Compose files.
  • Environment and secrets files.
  • Reverse proxy configuration.

Back up application files and create application-consistent database dumps. For PostgreSQL, that might include:

docker exec postgres-container \
  pg_dump -U app -d app --format=custom > app-$(date +%F).dump

For MySQL or MariaDB, use mysqldump or the backup method recommended for your database version.

Test restoring the backup to a separate environment. A backup process is not proven until a restore has succeeded.

VM snapshots are useful before a risky update, but they should complement rather than replace database-aware backups and off-server copies.

Common Docker Installation Problems

docker: permission denied while trying to connect to the Docker daemon socket

Your current user cannot access /var/run/docker.sock.

Use sudo docker ..., or add a trusted administrator to the Docker group:

sudo usermod -aG docker "$USER"

Then sign out and back in. Remember that Docker group membership is effectively root access.

docker: command not found

Confirm the packages are installed:

dpkg -l | grep -E 'docker-ce|docker-ce-cli'

If they are missing, repeat the repository and installation steps. Do not mix Docker's official packages with Ubuntu's docker.io package.

docker-compose: command not found

Use the current plugin syntax:

docker compose version

There is a space, not a hyphen.

If the plugin is absent:

sudo apt update
sudo apt install docker-compose-plugin

Cannot connect to the Docker daemon

Check the service:

sudo systemctl status docker --no-pager
sudo journalctl -u docker -n 100 --no-pager

Start it if necessary:

sudo systemctl start docker

port is already allocated

Another container or host process is already using the requested port:

sudo ss -ltnp | grep ':80'
docker ps --format 'table {{.Names}}	{{.Ports}}'

Stop the conflicting service or deliberately publish the container on another port. Do not kill an unknown production process without identifying it.

A container starts and immediately exits

Read its logs and inspect its exit code:

docker ps -a
docker logs --tail=200 container-name
docker inspect container-name --format '{{.State.ExitCode}}'

Common causes include a missing environment variable, invalid command, permission problem, failed database connection or incompatible image architecture.

The website works locally but not remotely

Check:

  1. The container is running.
  2. The port is published on the expected address.
  3. The host or provider firewall allows the port.
  4. DNS points to the correct server.
  5. A reverse proxy is configured for the correct upstream.

Useful commands:

docker compose ps
sudo ss -ltnp
curl -v http://127.0.0.1/

Docker consumes too much disk space

Inspect usage first:

docker system df -v
sudo du -sh /var/lib/docker

Look for old images, stopped containers and excessive application logs. Configure log rotation instead of repeatedly deleting logs after the disk fills.

Create or edit /etc/docker/daemon.json:

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

Validate the JSON before restarting Docker:

python3 -m json.tool /etc/docker/daemon.json
sudo systemctl restart docker

These defaults apply to newly created containers. Recreate existing containers if you need them to use the new logging configuration.

Ubuntu 26.04 or Ubuntu 24.04 for Docker?

Both releases are LTS versions and both are supported by Docker.

Choose Ubuntu 26.04 when:

  • You are building a new server.
  • Your application stack supports its newer libraries and kernel.
  • You want the longer remaining LTS lifecycle.

Choose Ubuntu 24.04 when:

  • A vendor explicitly certifies only 24.04.
  • You depend on older packages or third-party installation scripts.
  • You are cloning an established environment and want identical versions.

Do not upgrade a working production server only because a newer LTS exists. Test the application, volumes, firewall behaviour and rollback process on a separate server first.

Ubuntu's release notes state that an older Ubuntu 22.04 system must be upgraded through a supported intermediate release rather than jumping directly to 26.04. For container hosts, a fresh VPS followed by a controlled migration is often cleaner than several in-place operating system upgrades.

Running Docker on a HYEHOST VPS

Docker works well on a KVM VPS because containers receive a normal Linux kernel environment while the VPS retains its own isolated resources and operating system.

With a HYEHOST Cloud VPS, you can deploy an Ubuntu LTS image from the panel, use the browser console if SSH is not yet available, monitor network usage and expand the service as the container stack grows.

A practical starting point is:

Workload Suggested starting resources
Reverse proxy and one small website 2 vCPU, 2 GB RAM
Several small web applications 4 vCPU, 4 GB RAM
Applications plus PostgreSQL or Redis 4 vCPU, 4-8 GB RAM
CI workers, larger databases or many services 6+ vCPU, 8+ GB RAM

Actual usage depends on the applications. Check memory, CPU, storage and database growth after deployment rather than relying only on a generic estimate.

HYEHOST private networking can separate application and database VMs without sending internal traffic over the public internet. Additional HDD storage is useful for bulk data or secondary backup copies, while application databases generally benefit from the primary SSD storage.

When you are ready:

  1. Compare Cloud VPS plans.
  2. Deploy a server in the HYEHOST panel.
  3. Select an Ubuntu LTS image.
  4. Complete the official Docker installation above.
  5. Deploy the application with a reviewed Compose file.

Docker on Ubuntu 26.04 FAQ

Does Ubuntu 26.04 support Docker?

Yes. Ubuntu 26.04 LTS is listed as a supported Ubuntu release in Docker's official installation documentation.

Does Docker Compose need to be installed separately?

Install the docker-compose-plugin package alongside Docker Engine. It provides the current docker compose command. You do not need the legacy standalone docker-compose binary.

Should I install docker.io or docker-ce?

For the current Docker Engine packages and plugins, use docker-ce from Docker's official APT repository. Avoid installing both package families on the same server.

Is Docker free on Ubuntu?

Docker Engine is open source and can be installed on Ubuntu without a per-server licence fee. Docker Desktop has separate licensing terms, but Docker Desktop is not required for a headless Ubuntu VPS.

How much RAM does Docker need?

Docker Engine itself is relatively light, but containers determine the real requirement. A tiny web service may fit on a 1-2 GB server. Databases, Java applications, AI tools and multiple services commonly need 4 GB or more.

Will Docker containers start after a reboot?

Docker starts at boot when its systemd service is enabled. Individual containers also need an appropriate restart policy such as unless-stopped or always.

Does UFW protect Docker container ports?

Not always in the way administrators expect. Docker creates firewall rules for published ports, and those ports can bypass UFW rules. Publish only required ports, bind private services to localhost, and use the DOCKER-USER chain where forwarded traffic must be filtered.

Is it safe to add my user to the Docker group?

Only for trusted administrators. The Docker group grants capabilities that are effectively equivalent to root access.

Official References