How to Install Docker on Ubuntu (26.04, 24.04, 22.04)

If you want to install Docker on Ubuntu, Docker Engine packages applications and their dependencies into isolated containers so they run the same way on a laptop, a CI runner, or a production server. Common use cases include testing releases in clean environments, running services like databases without polluting the host, and building images for deployment.

This guide covers two supported paths: the official Docker APT repository for Ubuntu 24.04 and 22.04, plus the Ubuntu docker.io packages for Ubuntu 26.04. By the end, you will have Docker, Compose, and Buildx installed, non-root access configured, and a verified test container run.

System Requirements

This guide targets Ubuntu 26.04, 24.04, and 22.04 LTS. Docker Engine for Ubuntu is compatible with x86_64/amd64, arm64, armhf, s390x, and ppc64le (ppc64el) architectures; on x86_64 and arm64 this implies a 64-bit Ubuntu install. See the Docker Engine install guide for Ubuntu for the canonical support list.

Choose Your Docker Installation Method

Docker is packaged by Docker Inc. and by Ubuntu. Pick the method that matches your Ubuntu release and the update cadence you want.

MethodSourceBest ForUpdate Cadence
Official Docker APT repository (docker-ce)download.docker.comUbuntu 24.04 and 22.04 users who want upstream Docker packagesFast, direct from Docker Inc.
Ubuntu docker.io packagesUbuntu Universe repositoryUbuntu 26.04 users and environments where Docker’s repo is unavailableUbuntu-maintained, may lag behind upstream

For Ubuntu 24.04 and 22.04, the official Docker repository is recommended because it delivers the upstream engine plus the Compose and Buildx plugins. On Ubuntu 26.04, use the Ubuntu docker.io packages because Docker’s repository does not publish resolute packages.

This guide covers Ubuntu 26.04 LTS, 24.04 LTS, and 22.04 LTS. Docker’s APT repository publishes packages for 24.04 and 22.04 only, while Ubuntu 26.04 uses the docker.io packages from the Ubuntu repositories. Follow the method that matches your release.

If you use ufw or firewalld, be aware that Docker manages iptables rules directly. Docker supports iptables-nft and iptables-legacy, but rules created with nft are not supported. Review Docker’s packet filtering and firewall guidance before proceeding.

Remove Previous Docker Installations

If you previously installed Docker from another source, remove older packages first to avoid conflicts. Use the Ubuntu package removal command if you installed docker.io, and the Docker Engine removal command if you installed docker-ce from Docker’s repository.

Remove Ubuntu-packaged Docker components:

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

Remove Docker Engine packages from the Docker repository (if you installed them previously):

sudo apt remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

If you have not installed any of these packages, apt will report that nothing needs to be removed.

Clean up orphaned dependencies left behind by removed packages:

sudo apt autoremove

The following commands will permanently delete all Docker images, containers, volumes, and networks stored in /var/lib/docker/ and /var/lib/containerd/. Only run these if you want a completely clean Docker installation.

Delete existing Docker data if you want a fresh start:

sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

If you previously added Docker’s official repository, remove the sources file and keyring:

sudo rm /etc/apt/sources.list.d/docker.sources
sudo rm /usr/share/keyrings/docker.gpg

If these files do not exist, skip this step and continue.

Refresh your package index after cleanup:

sudo apt update

Method 1: Install Docker Engine from the official Docker APT repository (Ubuntu 24.04 and 22.04)

This method uses Docker’s upstream packages and includes the official Compose and Buildx plugins.

Add Docker’s APT repository

Install the tools needed to download the repository key. If you are new to curl, see our curl command guide for examples.

sudo apt install ca-certificates curl gpg

Download Docker’s GPG key and convert it into a keyring file that APT can use:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg
sudo chmod a+r /usr/share/keyrings/docker.gpg

The gpg --dearmor step converts the ASCII key into a binary keyring that APT can reference in the repository file.

Add the Docker repository using the modern DEB822 format:

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
Signed-By: /usr/share/keyrings/docker.gpg
EOF

This file reads your Ubuntu codename automatically, so the same command works on both 24.04 and 22.04.

Refresh your package index so APT sees the new Docker repository:

sudo apt update

You should see the Docker repository in the output (Ubuntu 24.04 example):

Get:1 https://download.docker.com/linux/ubuntu noble InRelease [48.5 kB]
Get:2 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages [50.7 kB]
Hit:3 http://archive.ubuntu.com/ubuntu noble InRelease
Hit:4 http://security.ubuntu.com/ubuntu noble-security InRelease
Hit:5 http://archive.ubuntu.com/ubuntu noble-updates InRelease
Hit:6 http://archive.ubuntu.com/ubuntu noble-backports InRelease
Fetched 99.2 kB in 1s (95.5 kB/s)
Reading package lists...
Building dependency tree...
Reading state information...
10 packages can be upgraded. Run 'apt list --upgradable' to see them.

Confirm that APT will install Docker from download.docker.com:

apt-cache policy docker-ce

Example output (Ubuntu 24.04):

docker-ce:
  Installed: (none)
  Candidate: 5:29.1.5-1~ubuntu.24.04~noble
  Version table:
     5:29.1.5-1~ubuntu.24.04~noble 500
        500 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages
     5:29.1.4-1~ubuntu.24.04~noble 500
        500 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages
     5:29.1.3-1~ubuntu.24.04~noble 500
        500 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages
     5:29.1.2-1~ubuntu.24.04~noble 500
        500 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages

Install Docker Engine

Install Docker Engine and the official Compose and Buildx plugins:

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

Verify the installed versions:

docker --version
docker compose version
docker buildx version

Expected output (Ubuntu 24.04/22.04):

Docker version 29.1.5, build 0e6fee6
Docker Compose version v5.0.1
github.com/docker/buildx v0.30.1 9e66234aa13328a5e75b75aa5574e1ca6d6d9c01

Method 2: Install Docker from Ubuntu’s docker.io package (Ubuntu 26.04)

This method uses Ubuntu’s packaged Docker Engine. Compose and Buildx are separate packages in the Ubuntu repositories.

Update your package index:

sudo apt update

Install Docker, Compose, and Buildx from the Ubuntu repositories:

sudo apt install docker.io docker-compose-v2 docker-buildx

If apt cannot locate these packages, enable the Universe repository (common on minimal installs):

sudo apt install software-properties-common
sudo add-apt-repository universe

After enabling Universe, re-run the install command above.

Verify the installed versions:

docker --version
docker compose version
docker buildx version

Expected output (Ubuntu 26.04):

Docker version 29.1.3, build 29.1.3-0ubuntu1
Docker Compose version 2.40.3+ds1-0ubuntu1
github.com/docker/buildx 0.30.1 0.30.1-0ubuntu1

Run a Test Container

After either installation method, run the hello-world container to confirm the Docker daemon can pull images and start containers:

sudo docker run --rm hello-world

Successful output looks like:

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

The docker command requires root privileges by default. The next section covers configuring non-root user access so you can run Docker without sudo.

Managing Docker with systemd on Ubuntu

Docker installs systemd unit files at /usr/lib/systemd/system/docker.service and /usr/lib/systemd/system/docker.socket, so you can manage the daemon with standard systemctl commands.

sudo systemctl start docker.service

This starts the Docker service immediately for the current session. Use the enable command below if you want it to start automatically at boot.

sudo systemctl stop docker.service

This stops the Docker service until you start it again or reboot. It does not change whether Docker auto-starts on boot.

sudo systemctl restart docker.service

Restarts the Docker service.

sudo systemctl status docker.service

Displays the current status of the Docker service.

sudo systemctl enable docker.service

Enables the Docker service to start automatically on system boot. Docker installs with this enabled by default, but use this command if you previously disabled auto-start.

sudo systemctl disable docker.service

Disables automatic startup of the Docker service on system boot. The service remains available for manual start with systemctl start docker.service, but won’t launch during boot.

Docker Configuration and Usage

Manage Docker as a non-root user on Ubuntu

When running Docker, avoid using the root user to prevent security risks and accidental changes to the host system. Instead, manage Docker as a non-root user by adding users to the docker group, or consider rootless mode for tighter isolation.

If you want to add a new user for Docker management, use the following command:

sudo useradd -m dockeruser

Verify the new account exists:

id dockeruser
uid=1001(dockeruser) gid=1001(dockeruser) groups=1001(dockeruser)

If the user already exists, skip this step.

To add your current user to the docker group, run:

sudo usermod -aG docker $USER

The Docker group grants root-equivalent privileges to users. Members can access the Docker daemon socket, which provides full control over the host system. Only add trusted users to this group, as they can escape container isolation and modify host files. For production environments, consider using rootless Docker mode or implementing proper access controls.

If you want to grant access to a different account, replace $USER with that username.

After adding a user to the Docker group, you have two options to activate the group membership:

Option 1: Activate immediately without logging out using the newgrp command:

newgrp docker

This starts a new shell session with the docker group active, allowing you to run Docker commands immediately.

Option 2: Log out and back in, or reboot your system for the changes to take effect system-wide.

To ensure the user can run Docker commands, use the following command:

docker ps

If Docker is working correctly with your user account, you should see an empty container list:

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

This confirms Docker commands run without sudo. If you see a permission error instead, verify the group membership activated correctly or try logging out and back in.

If you encounter permission errors when running Docker commands (such as errors accessing ~/.docker/config.json), fix the ownership and permissions on the Docker configuration directory:

sudo chown "$USER":"$USER" "$HOME/.docker" -R
sudo chmod -R g+rwx "$HOME/.docker"

These commands set the correct ownership and permissions for your user’s Docker configuration directory, resolving common permission-related issues. If you want a refresher on chmod flags, see our chmod command guide.

Configure Log Rotation

By default, Docker logs to the JSON file format without size limits. This can consume unlimited disk space over time.

Docker’s default json-file logging driver does not limit log file size or implement automatic rotation. Without proper configuration, containers can consume unlimited disk space through logging, potentially filling your filesystem. Always configure log rotation with max-size and max-file options in production environments to prevent disk exhaustion.

To configure log rotation, create the Docker daemon configuration file:

sudo nano /etc/docker/daemon.json

If /etc/docker/daemon.json already exists, merge these log settings with your current JSON instead of replacing the file.

Add the following configuration to limit log file size and count:

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

This configuration limits each container’s log file to 10 megabytes and keeps a maximum of 3 rotated log files. Adjust these values based on your storage capacity and logging requirements.

After creating the file, restart the Docker daemon to apply the changes:

sudo systemctl restart docker.service

Existing containers retain their original logging configuration. Only containers created after this change will use the new log rotation settings.

Docker Command Reference

The following table summarizes commonly used Docker commands for managing containers, images, networks, and volumes:

CommandDescription
docker runRun a new container from an image.
docker psList all running containers.
docker imagesList all available images.
docker buildBuild a new image from a Dockerfile.
docker stopStop a running container.
docker rmRemove a container.
docker rmiRemove an image.
docker networkManage Docker networks.
docker volumeManage Docker volumes.
docker infoDisplay system-wide Docker information.
docker searchSearch Docker Hub for images.

View Docker System Information

The docker info command displays comprehensive system-wide information about your Docker installation, including the number of containers and images, storage driver details, and system resources.

docker info

This displays detailed information about your Docker environment, helping you verify configuration and troubleshoot issues. The output includes container and image counts, storage driver type, kernel version, and available plugins.

Search Docker Hub for Images

The docker search command searches Docker Hub for publicly available images matching your search term. This helps you discover official images and community-maintained alternatives before pulling them.

docker search ubuntu

This searches Docker Hub for images containing “ubuntu” in their name or description. The results include the image name, description, star count, and whether it’s an official image. Official images are labeled as “Official” and typically have clearer maintenance and documentation signals.

Run Containers from Images

The docker run command creates and starts a new container from an image. For example, to run a container from the ubuntu image:

docker run -it ubuntu:latest /bin/bash

This starts a new container from the ubuntu image and opens a shell inside the container.

List Running Containers

The docker ps command lists all running containers and provides information about each, including container ID, image name, and status.

docker ps

This displays a list of all running containers.

List Downloaded Images

The docker images command lists all available images and supplies information about each image, including image ID, repository, and tag.

docker images

This displays a list of all available images.

Build Images from Dockerfiles

The docker build command builds a new image from a Dockerfile, a script containing instructions for building an image.

docker build -t myimage:latest .

This builds a new image called myimage using the Dockerfile in the current directory.

Stop Running Containers

The docker stop command stops a running container. For example, to stop a container with the ID abcdefg:

docker stop abcdefg

This stops the container with the ID abcdefg.

Remove Containers

Use the docker rm command to remove a container. For example, to eliminate a container with the ID abcdefg:

docker rm abcdefg

This removes the container with the ID abcdefg.

Remove Images

The docker rmi command removes an image. For example, to eliminate an image with the ID 1234567:

docker rmi 1234567

This removes the image with the ID 1234567.

Manage Docker Networks

The docker network command manages Docker networks. It offers options to create, list, and remove networks.

docker network create mynetwork

This creates a new network called mynetwork.

Manage Docker Volumes

The docker volume command manages Docker volumes, providing options to create, list, and remove volumes.

docker volume create myvolume

This creates a new volume called myvolume.

Save Container Changes as Images

When working with Docker containers, changing the container you want to save as a new image is common. You can use the docker commit command to commit changes in a container to a Docker image.

First, start a new container from the base image and make any necessary changes to the container. For example, to start a new container from the ubuntu image and open a shell inside the container, you can use the following command:

docker run -it --name mycontainer ubuntu:latest /bin/bash

This command will start a new container from the ubuntu image and open a shell inside the container. You can make any necessary changes to the container, such as installing new software or modifying configuration files.

Once you have made the necessary changes, you can use the docker commit command to create a new image from the container. For example, to create a new image called myimage with the changes made in the mycontainer container, you can use the following command:

docker commit mycontainer myimage:latest

This command will create a new image called myimage with the changes made in the mycontainer container. You can now use this new image to create and run new containers with the updated software or configuration.

It’s important to note that the docker commit command only saves changes made to the container’s file system and does not save changes to the container’s networking or storage. If you need to save changes to these areas, use other Docker commands, such as docker network or docker volume.

Security Best Practices

Securing your Docker installation protects both containers and the host system from potential vulnerabilities. Follow these essential security practices when working with Docker on Ubuntu:

Run containers with least privilege: Avoid running containers as root when possible. Use the --user flag to specify a non-root user inside containers, limiting potential damage if a container is compromised.

Keep Docker updated: Regularly update Docker and the host system to receive security patches and bug fixes. Subscribe to Docker security advisories and apply updates promptly.

Docker CE packages (official repository):

sudo apt update && sudo apt install --only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Ubuntu docker.io packages:

sudo apt update && sudo apt install --only-upgrade docker.io docker-compose-v2 docker-buildx

These sequences refresh the package lists and upgrade only the Docker components, leaving the rest of your system untouched.

Consider configuring unattended-upgrades to automatically apply security updates to Docker and the host system, ensuring your environment stays protected against known vulnerabilities.

Enable Docker Content Trust: Docker Content Trust uses digital signatures to verify the publisher and integrity of images. See the Content Trust documentation for details, then enable it by setting the environment variable:

export DOCKER_CONTENT_TRUST=1

This ensures you only pull signed and verified images from trusted publishers.

Limit network exposure: Only expose necessary ports when running containers. Use specific port mappings instead of exposing all ports, and bind to localhost (127.0.0.1) instead of 0.0.0.0 when services don’t need external access. For remote management, use SSH tunneling to access container services securely.

docker run -p 127.0.0.1:8080:80 nginx

This runs an Nginx container with port 80 only accessible from the local machine on port 8080.

Scan images for vulnerabilities: Use Docker Scout or third-party tools to scan images for known security vulnerabilities before deploying them to production.

Implement resource limits: Prevent containers from consuming excessive system resources by setting memory and CPU limits using the --memory and --cpus flags.

Monitor for intrusion attempts: Use Fail2ban on your host system to detect and block repeated unauthorized access attempts to services running in containers.

Troubleshooting Common Issues

These fixes cover the most common Docker issues on Ubuntu.

Docker daemon is not running

If the Docker daemon is not running, Docker CLI commands report a connection error. Run docker info and look for the server error below:

docker info
Client: Docker Engine - Community
 Version:    29.1.5
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.30.1
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v5.0.1
    Path:     /usr/libexec/docker/cli-plugins/docker-compose

Server:
failed to connect to the docker API at unix:///var/run/docker.sock; check if the path is correct and if the daemon is running: dial unix /var/run/docker.sock: connect: no such file or directory

Start and enable the Docker service:

sudo systemctl start docker
sudo systemctl enable docker

Verify the fix by re-running the hello-world test container from the earlier verification step.

Permission denied connecting to the Docker socket

If you run Docker commands without sudo and see a socket permission error, the output looks like:

permission denied while trying to connect to the docker API at unix:///var/run/docker.sock

Check whether your user is in the docker group:

groups $USER
joshua adm dialout cdrom floppy sudo audio dip video plugdev users netdev docker

If docker is missing, add your user to the group and activate it:

sudo usermod -aG docker $USER
newgrp docker

If you prefer not to use newgrp, log out and back in to apply group changes system-wide.

Confirm the socket permissions are owned by root:docker:

ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0 Jan 14 19:56 /var/run/docker.sock

Verify access by listing containers:

docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Container networking issues

If containers cannot reach external networks or other containers, verify Docker’s network configuration:

docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
e0f4b42f45f7   bridge    bridge    local
2b92e331d2c7   host      host      local
359d4c681ec9   none      null      local

If the bridge network is missing, restart Docker with sudo systemctl restart docker to recreate the default networks. If you use ufw or firewalld, review the firewall warning at the beginning of this guide, as these firewalls may block container traffic by default.

Test container networking by running a simple network test:

docker run --rm busybox ping -c 3 google.com
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
e59838ecfec5: Pulling fs layer
0f4360cf3c3e: Download complete
e59838ecfec5: Download complete
e59838ecfec5: Pull complete
Digest: sha256:2383baad1860bbe9d8a7a843775048fd07d8afe292b94bd876df64a69aae7cb1
Status: Downloaded newer image for busybox:latest
PING google.com (142.250.124.138): 56 data bytes
64 bytes from 142.250.124.138: seq=0 ttl=63 time=38.637 ms
64 bytes from 142.250.124.138: seq=1 ttl=63 time=37.094 ms
64 bytes from 142.250.124.138: seq=2 ttl=63 time=37.385 ms

--- google.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 37.094/37.705/38.637 ms

If this fails, check your host’s DNS configuration and ensure Docker can access /etc/resolv.conf.

Remove Docker from Ubuntu

Use the removal path that matches how you installed Docker.

Remove Docker Engine packages (official Docker repository)

Uninstall Docker Engine, the CLI, containerd, and the plugin packages:

sudo apt purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras

Remove unused dependencies:

sudo apt autoremove

Remove the Docker repository and keyring:

sudo rm /etc/apt/sources.list.d/docker.sources
sudo rm /usr/share/keyrings/docker.gpg

Refresh the package index:

sudo apt update

Verify the Docker CE packages are gone:

dpkg -l docker-ce
dpkg-query: no packages found matching docker-ce

Remove Ubuntu docker.io packages

Uninstall the Ubuntu-packaged engine and plugins:

sudo apt purge docker.io docker-compose-v2 docker-buildx

Remove unused dependencies:

sudo apt autoremove

Verify the packages are gone:

dpkg -l docker.io
dpkg-query: no packages found matching docker.io

The following commands permanently delete all Docker images, containers, volumes, and custom networks. This action cannot be undone. Back up any important container data before proceeding.

Delete Docker data directories:

sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

Removing /etc/docker deletes daemon configuration files such as daemon.json. Back up any custom settings before deleting this directory.

Remove custom Docker daemon configuration:

sudo rm -rf /etc/docker

Docker Documentation and Resources

Explore these official Docker resources for further learning:

Conclusion

You now have Docker installed on Ubuntu using the method that matches your release, along with Compose and Buildx for modern workflows. The setup includes systemd service management, non-root user access through the docker group, and security best practices like log rotation. From here, explore Docker Compose for multi-container applications and expand your container networking as needed.

Leave a Comment

Let us know you are human: