hieuvnlabs logo
Hiusvu

How To Install Docker and Docker Compose on Ubuntu

Published on September 2, 2026

How To Install Docker and Docker Compose on Ubuntu

Introduction

Docker lets you package an application together with all of its dependencies into a container and run it anywhere Docker is installed. Compared with virtual machines, containers are far lighter because they share the host kernel, start in seconds and are easy to replicate.

In this guide we will install Docker Engine from Docker's official repository on Ubuntu, configure it so you can run docker without sudo, walk through the essential commands, and install Docker Compose to manage multi-container applications.

Prerequisites

  • A server running Ubuntu 20.04 or 22.04 (64-bit).
  • A regular user with sudo privileges.

Step 1 — Removing Old Docker Versions

Ubuntu ships a docker.io package in its default repository, but it is usually outdated. To make sure you get the latest release from Docker, remove any old packages first:

sudo apt remove docker docker-engine docker.io containerd runc

If apt reports that none of these packages are installed, that is fine.

Step 2 — Adding Docker's Official Repository

Update the package index and install the packages that let apt use a repository over HTTPS:

sudo apt update
sudo apt install ca-certificates curl gnupg lsb-release

Create the keyring directory and add Docker's official GPG key:

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

Add the Docker repository to your apt sources:

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Refresh the package index so apt sees the new repository:

sudo apt update

Check which repository apt will install Docker from:

apt-cache policy docker-ce
Output
docker-ce:
  Installed: (none)
  Candidate: 5:24.0.7-1~ubuntu.22.04~jammy
  Version table:
     5:24.0.7-1~ubuntu.22.04~jammy 500
        500 https://download.docker.com/linux/ubuntu jammy/stable amd64 Packages

docker-ce is not installed yet and the candidate comes from download.docker.com, so the repository was added correctly.

Step 3 — Installing Docker Engine

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

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

Docker starts automatically after installation. Check its status:

sudo systemctl status docker
Output
 docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2026-09-02 09:20:11 UTC; 30s ago
TriggeredBy:  docker.socket
       Docs: https://docs.docker.com
   Main PID: 4128 (dockerd)
      Tasks: 9
     Memory: 32.1M

Check the version:

docker --version
Output
Docker version 24.0.7, build afdd53b

Step 4 — Running Docker Without sudo

By default the docker command can only be run by root or by users in the docker group. If you run it as a regular user you get:

Output
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock

To avoid typing sudo every time, add your user to the docker group:

sudo usermod -aG docker ${USER}

Log out and back in for the change to take effect, or run the following to reload group membership in the current session:

newgrp docker

Confirm your user is in the docker group:

groups
Output
hiusvu sudo docker

Note: Members of the docker group effectively have root privileges on the host, because they can mount any directory into a container. Only add users you trust.

Step 5 — Testing With the hello-world Container

Run the hello-world image to confirm Docker works end to end:

docker run hello-world
Output
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete
Digest: sha256:d000bc569937abbe195e20322a0bde6b2922d805332fd6d8a68b19f524b7d21d
Status: Downloaded newer image for hello-world:latest

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

Docker could not find the image locally, so it pulled it from Docker Hub, created a container from it, ran it and printed the message.

Step 6 — Essential Docker Commands

These are the commands you will use every day.

Working with images

Search Docker Hub for an image:

docker search ubuntu

Pull an image to your machine:

docker pull ubuntu

List the images on your machine:

docker images

Remove an image:

docker rmi ubuntu

Working with containers

Run an Ubuntu container and open an interactive shell inside it (-i keeps stdin open, -t allocates a terminal):

docker run -it ubuntu

Inside the container you can install packages just like on a normal Ubuntu machine. Type exit to leave.

Run a container in the background (-d), give it a name and map port 8080 on the host to port 80 in the container:

docker run -d --name web -p 8080:80 nginx

List running containers:

docker ps

List all containers, including stopped ones:

docker ps -a

View a container's logs:

docker logs -f web

Open a shell inside a running container:

docker exec -it web bash

Stop, start and remove a container:

docker stop web
docker start web
docker rm web

Clean up all stopped containers, unused images and dangling networks:

docker system prune

Step 7 — Using Docker Compose

Docker Compose lets you define and run multi-container applications from a single YAML file. The docker-compose-plugin was installed in Step 3. Check it:

docker compose version
Output
Docker Compose version v2.21.0

Create a project directory and a sample docker-compose.yml with an Nginx web server and a MySQL database:

mkdir ~/compose-demo && cd ~/compose-demo
nano docker-compose.yml
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
    depends_on:
      - db

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: app
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

Create a sample HTML page:

mkdir html
echo "<h1>Hello from Docker Compose</h1>" > html/index.html

Start all services in the background:

docker compose up -d

Check the status of the services:

docker compose ps

Visit http://your_server_ip:8080 to see the sample page. When you want to stop and remove the project's containers and networks:

docker compose down

Add the -v flag to also remove the data volumes:

docker compose down -v

Conclusion

You have installed Docker Engine from the official repository, configured it to run without sudo, learned the core image and container commands, and used Docker Compose to run a multi-service application. From here you can:

  • Write a Dockerfile to package your own application.
  • Run services like MySQL, Redis or PostgreSQL through Compose instead of installing them directly on the host.
  • Put Nginx in front as a reverse proxy to host several apps on one VPS.