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
sudoprivileges.
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 runcIf 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-releaseCreate 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.gpgAdd 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/nullRefresh the package index so apt sees the new repository:
sudo apt updateCheck which repository apt will install Docker from:
apt-cache policy docker-ceOutput
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 Packagesdocker-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-pluginDocker starts automatically after installation. Check its status:
sudo systemctl status dockerOutput
● 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.1MCheck the version:
docker --versionOutput
Docker version 24.0.7, build afdd53bStep 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.sockTo 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 dockerConfirm your user is in the docker group:
groupsOutput
hiusvu sudo dockerNote: 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-worldOutput
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 ubuntuPull an image to your machine:
docker pull ubuntuList the images on your machine:
docker imagesRemove an image:
docker rmi ubuntuWorking with containers
Run an Ubuntu container and open an interactive shell inside it (-i keeps stdin open, -t allocates a terminal):
docker run -it ubuntuInside 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 nginxList running containers:
docker psList all containers, including stopped ones:
docker ps -aView a container's logs:
docker logs -f webOpen a shell inside a running container:
docker exec -it web bashStop, start and remove a container:
docker stop web
docker start web
docker rm webClean up all stopped containers, unused images and dangling networks:
docker system pruneStep 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 versionOutput
Docker Compose version v2.21.0Create 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.ymlservices:
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.htmlStart all services in the background:
docker compose up -dCheck the status of the services:
docker compose psVisit 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 downAdd the -v flag to also remove the data volumes:
docker compose down -vConclusion
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
Dockerfileto 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.

