BASIC
Tested for real: I ran every command in this guide top-to-bottom on a fresh Ubuntu 24.04 virtual machine (4 CPUs, 8 GB RAM) on 13 August 2026. Versions at test time: Docker Engine 29.7.2, Docker Compose v5.4.0, containerd 2.3.3, Buildx v0.36.1, on Ubuntu 24.04.4 LTS.
Found a problem? Tell me via the contact page.
What you'll end up with
Docker installed from Docker's own package source, the way their documentation says to do it. You will run a real container and see it work. You will also know how to remove every trace of it, because I tested that too.
Hello from Docker!
This message shows that your installation appears to be working correctly.
Who this is for
BASIC. One path, copy-paste-safe, no branching. If you can open a terminal on your Ubuntu server, you can do this.
Time and cost
The commands themselves took under 3 minutes of machine time when I ran them. Allow 20 minutes end to end, including reading and one log-out-and-back-in. Cost: free. About 400 MB of disk space.
Words you'll meet
- Container — a way to run a program in its own sealed box, with everything it needs packed inside. See /basics.
- Image — the frozen template a container starts from. You download an image once; you can run many containers from it.
- Repository — a source your system downloads software from. Ubuntu has its own; here we add Docker's.
- GPG key — a signature file. Your system uses it to check that downloaded packages really came from Docker.
- Daemon — a program that runs in the background. Docker's daemon does the actual work; the
dockercommand talks to it. - Compose — Docker's tool for describing a whole service in one file. We only check it exists today; it gets its own guide.
Placeholders
Anywhere you see CAPS-WITH-DASHES like YOUR-USERNAME-HERE, swap in your own value. This guide uses one — YOUR-USERNAME-HERE in the group commands near the end; everything else is copy-paste as written.
Before you start
- An Ubuntu 24.04 server you can log into.
- A normal user account with sudo, not root. If you set the server up with my first hour guide, you have this.
- An internet connection on the server.
A note before the first command
If you have seen older Docker guides, many still say apt-key add. Do not use them. apt-key is deprecated and should not be used in new guides. The modern pattern is a keyring file plus signed-by, which is exactly what Docker's own documentation does — and what we do below.
The steps
Step 1 — Clear out any old Docker bits
Ubuntu ships its own, older Docker packages under different names. They clash with the official ones, so Docker's docs say to remove them first. This is Docker's own removal loop, copied exactly.
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove -y $pkg; done
Check it worked. On a fresh machine you'll see a string of "not installed" lines — that is the good outcome:
Package 'docker-compose' is not installed, so not removed
Package 'containerd' is not installed, so not removed
0 upgraded, 0 newly installed, 0 to remove and 26 not upgraded.
The important line is 0 upgraded, 0 newly installed, 0 to remove. If it removed real packages instead, that's fine too. That was the point.
Step 2 — Download Docker's signing key
First, refresh the package lists and make sure the two tools we need are present.
sudo apt-get update
sudo apt-get install -y ca-certificates curl
A passing run includes:
ca-certificates is already the newest version (20260601~24.04.1).
curl is already the newest version (8.5.0-2ubuntu10.11).
Your versions may be newer — that's fine.
Now make the folder where Ubuntu keeps signing keys. It may already exist; this command is safe either way.
sudo install -m 0755 -d /etc/apt/keyrings
Download Docker's key into that folder, and make it readable.
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
Check it worked.
ls -l /etc/apt/keyrings/docker.asc
The important line is:
-rw-r--r-- 1 root root 3817 Aug 13 16:05 /etc/apt/keyrings/docker.asc
The -rw-r--r-- at the start matters — the key is readable by everyone, as apt needs. The three commands before this print nothing on success — silence is normal here.
Step 3 — Tell Ubuntu about Docker's repository
This long command writes one line into a file. The line says: fetch Docker packages from download.docker.com, and only trust them if they're signed by the key we just saved. The $(...) parts fill in your machine's details automatically — no editing needed.
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Check it worked.
cat /etc/apt/sources.list.d/docker.list
Your output will vary, but look for:
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable
Your architecture and codename fill in the amd64 and noble slots; the shape of the line is what matters.
Now refresh the package lists again, so Ubuntu reads that new file.
sudo apt-get update
A passing run includes:
Get:1 https://download.docker.com/linux/ubuntu noble InRelease [48.5 kB]
Hit:2 http://archive.ubuntu.com/ubuntu noble InRelease
[...snipped...]
The load-bearing line is the download.docker.com one. If it's there with no errors, the repository is trusted and live.
Step 4 — Install Docker
Five packages: the engine, the command-line tool, the container runtime, and the Buildx and Compose plugins. This is the exact set Docker's documentation installs.
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
In my test this downloaded 102 MB and finished in 20 seconds. On a slower line, expect a few minutes.
Check it worked. Docker starts itself immediately — verify that:
sudo systemctl is-active docker
active
One word, active, is the whole answer.
Step 5 — Run your first container
hello-world is Docker's tiny self-test image. This one command downloads it, runs it, and prints a message from inside the container.
sudo docker run hello-world
You should see something like:
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
[...snipped...]
Hello from Docker!
This message shows that your installation appears to be working correctly.
[...snipped...]
The important line is Hello from Docker! — that message was produced inside a container. Docker works.
Step 6 — Drop the sudo (and understand what that costs)
Right now only sudo can talk to Docker. Try it without:
docker ps
The important line is:
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock
The fix is adding yourself to the docker group. But be honest with yourself about what this means: membership of the docker group is effectively root access. Anyone in that group can start a container that mounts the whole disk and read anything on the machine. Docker's own docs say the same. On a personal server that trade is usually fine; on a shared machine, think first — sticking with sudo docker is a valid choice.
sudo usermod -aG docker YOUR-USERNAME-HERE
(Or use $USER and it fills in your name automatically.)
Group changes only apply to new logins. Log out, log back in, then:
Check it worked.
groups
Your output will vary, but look for:
tester docker
The important word is docker at the end of your group list. And now, no sudo needed:
docker run hello-world
Hello from Docker!
[...snipped...]
Step 7 — Confirm Compose came along
The Compose plugin installed in step 4. One check now saves confusion later.
docker compose version
You should see something like:
Docker Compose version v5.4.0
Your version may be newer — that's fine. Note the command is docker compose with a space. The old hyphenated command is legacy; use the plugin form here. If a guide tells you to install docker-compose, that guide is out of date.
Something went wrong?
- You see
permission denied ... docker.sock→ it means your user isn't in the docker group yet, or you haven't logged out and back in since adding it → log out fully (close the terminal or SSH session) and log back in, then rungroupsto confirmdockeris listed. - You see
groupswithoutdockerin an old terminal, but a new login shows it → it means group membership is stamped at login time → any terminal opened before the change won't have it. New login, new powers. - You see
E: Package 'docker-ce' has no installation candidate→ it means step 3's repository line didn't take → runcat /etc/apt/sources.list.d/docker.list, compare with the expected output above, thensudo apt-get updateand look for the download.docker.com line.
Undo all of this
Tested for real on the same machine, straight after the install. Five commands take you back to a Docker-free system.
Remove the packages and their configuration:
sudo apt-get purge -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
Delete all images, containers and volumes. This is the destructive one — anything you built in Docker goes with it.
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
Remove the repository and key we added:
sudo rm /etc/apt/sources.list.d/docker.list
sudo rm /etc/apt/keyrings/docker.asc
Check it worked.
docker --version
docker: command not found
The refusal is the pass mark.
Optionally, take yourself back out of the (now empty) docker group:
sudo gpasswd -d YOUR-USERNAME-HERE docker
Removing user tester from group docker
Where to go next
- Docker Compose for real: one file, whole service — and the firewall trap — the GOING FURTHER follow-on, where Docker starts earning its keep.
- Official reference: docs.docker.com/engine/install/ubuntu — this guide follows it step for step, with real outputs added.
Last tested: 13 August 2026 on Ubuntu 24.04.4. Versions: Docker Engine 29.7.2, Compose v5.4.0, containerd 2.3.3, Buildx v0.36.1.
Tried it? Improved it?
Tell the forum what worked and what didn’t: real experience beats recommendations, and the best answers get folded back into this guide with credit.
Related guides
SSH keys, properly: never type a server password again
Your laptop will hold a small pair of files called an SSH key. Your server will trust it, so logging in never asks for a password — then we turn password logins off completely.
12 min read
First hour with a new Ubuntu server: locking the doors
A fully updated server, a personal account with admin rights, a firewall that blocks everything except SSH, and security updates that install themselves.
10 min read