Best Way to Install Docker on Ubuntu: Practical, Reliable Workflow
Many teams default to apt install docker.io
when provisioning Ubuntu servers. It works, but it’s not the approach you want for up-to-date CI runners or production hosts. The official Docker APT repository provides later releases, security patches, and a simpler upgrade path. The following installation process has been battle-tested on Ubuntu 20.04 and 22.04 LTS.
Situation: Legacy Package Headaches
Outdated Docker binaries ship through docker.io
(currently ~24.0.5 as of Ubuntu 22.04), but Docker Inc.’s own releases often bump security and API support months earlier. Sometimes, integrations like buildx
or Compose CLI won’t function as expected on the stock Canonical package. That’s why direct repo integration is preferable.
Quick Install Checklist
Prerequisites:
- Ubuntu 18.04, 20.04, or 22.04 (tested)
- sudo privileges
- Clean state: no conflicting
docker
,docker-engine
, ordocker.io
remnants
1. Update and Prepare the Host
Avoid dependency drift—update before touching repositories:
sudo apt update && sudo apt upgrade -y
2. Remove Conflicting Packages
If you’re migrating from stock Ubuntu Docker, remove legacy packages:
sudo apt remove docker docker-engine docker.io containerd runc
Note: Images and containers remain on disk under /var/lib/docker
. Data is not lost at this stage.
3. Install Transport Dependencies
Docker’s debs arrive over HTTPS; setup is essential:
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
4. Fetch Docker’s GPG Key
GPG verification prevents signature spoofing. As of late 2023, the key must reside here:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
Gotcha: If /usr/share/keyrings
does not exist, create it (sudo mkdir -p /usr/share/keyrings
).
5. Add the Official Docker Repository
Use the correct codename, e.g., jammy
for 22.04 or focal
for 20.04:
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
6. Sync Repositories and Pin Candidates
Update sources, then verify apt resolves docker-ce
from the correct repo:
sudo apt update
apt-cache policy docker-ce | grep download.docker.com
You should see a candidate line referencing download.docker.com
.
If not, the repo wasn’t added properly or the key step failed.
7. Install Docker Engine
Pull in docker-ce
, its CLI, and the Docker containerd runtime:
sudo apt install -y docker-ce docker-ce-cli containerd.io
On some systems, you may see an error about held packages; resolve by confirming no old Snap/Flatpak packages block installation.
8. Smoke Test: Hello World
Verify the daemon by running a disposable container:
sudo docker run --rm hello-world
Should print:
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
If you see “Cannot connect to the Docker daemon,” check if the service is active:
sudo systemctl status docker
(Optional) Run Docker Without Sudo
To avoid prefixing every command with sudo
:
sudo usermod -aG docker $USER
Important: You must log out and back in, or newgrp docker
for the group change to take effect. Not recommended for sensitive production environments—risks process privilege escalation.
Keeping Up to Date
When security updates drop (e.g., CVE-2023-3772), upgrade via:
sudo apt update
sudo apt install --only-upgrade docker-ce docker-ce-cli containerd.io
Tip: For pinning a specific version, list available with apt-cache madison docker-ce
.
Useful Post-Install Commands
-
List all containers:
docker ps -a
-
Show images and their digests:
docker images --digests
-
Alias for resource cleanup:
alias docker-clean='docker system prune -f --volumes'
-
Pull and run a specific image version (ex: Alpine 3.18):
docker run --rm -it alpine:3.18 sh
Known Issues
-
Snap Conflict:
Recent Ubuntu installations ship with Docker pre-installed via Snap, which interferes with APT-based Docker. Remove with:sudo snap remove docker
If the APT install still fails, check with
which docker
to confirm no misrouted binaries. -
Firewalling:
Docker manipulates iptables rules directly. If you rely on UFW or nftables for traffic isolation, configurations may conflict.
Closing Thoughts
Deploying Docker via the official repository is the only way to guarantee you’re running recent, secure, and compatible releases on Ubuntu. For production, enable version pinning and automate image vulnerability scans (see trivy
or Docker Scout). If a system uses LVM or ZFS, pay attention to Docker’s storage driver selection—can’t be swapped on a live system without full container/image migration.
Questions about alternative storage drivers or integrating Compose V2? Dig into the fine print of Docker’s release notes before deploying at scale.