Master the Basics - How to Install Docker on Ubuntu 24.04
Securely Install Docker on Ubuntu 24.04: A Step-by-Step Guide with Security In Mind

What Is Docker and Why Should You Use It?
Docker is a containerization platform that lets you run applications in isolated environments called containers. These containers package an application with all its dependencies, making them lightweight, portable, and easy to manage.
Why Use Docker?
Simplifies Application Deployment
Instead of installing software directly on your server (which can lead to dependency conflicts), Docker packages everything into self-contained units that run the same way on any system.
Saves System Resources
Unlike virtual machines (VMs), Docker containers share the host OS kernel, making them far more efficient with memory and CPU usage. You can run dozens of containers on one machine without the overhead of multiple full operating systems.
Easy Software Management
Need to install Jellyfin, Sonarr, Radarr, or Home Assistant? With Docker, it’s as easy as running a command to pull the application and all its dependencies—no manual configuration required.
Keeps Applications Isolated
Docker isolates applications from each other. If one container crashes or gets compromised, it won’t affect the rest of your system.
Effortless Updates and Rollbacks
Updating an app is as simple as pulling the latest container image. And if something goes wrong? Just roll back to the previous version with ease.
Now that you know why Docker is such a powerful tool for your home server, let’s install it correctly, with security in mind.
1. Update Your System and Install Dependencies
Before installing Docker, your system needs to be updated. Additionally, the necessary dependencies also need to be installed. These steps ensure a clean, stable installation. Run the following commands:
sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg
These commands:
- Update your package list (
apt update
) - Upgrade installed packages (
apt upgrade -y
) - Install the essential dependencies (if
curl
andgnupg
are not already installed)
2. Add Docker’s Official GPG Key and Repository
Ubuntu includes Docker in its default repositories, but you should not use it. Why?
- Outdated versions: Ubuntu’s repository often lags behind Docker’s latest stable releases, meaning you could be missing important features and security fixes.
- Slower updates: Critical bug fixes and security patches may take longer to arrive in Ubuntu’s repositories. Where Docker’s official repository adds these patches immediately.
- Missing features: The Ubuntu version may lack support for new Docker functionalities.
To install the latest version, add Docker’s official repository run the following commands:
TL;DR - I Just Want to Cut & Paste Commands:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo tee /etc/apt/keyrings/docker.asc > /dev/null
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
The Long and Detailed Explanation of the Commands:
sudo install -m 0755 -d /etc/apt/keyrings
Breaking It Down:
sudo
→ Runs the command with superuser (root) privileges.install
→ A command that can copy files, set permissions, and create directories.-m 0755
→ Sets the permissions of the directory to0755
(read & execute for everyone, write for the owner).-d
→ Tellsinstall
to create a directory (if it doesn’t exist)./etc/apt/keyrings
→ The path where the directory is created. This is where trusted GPG keys for package signing are stored.
🔒 Security Purpose:
- Ensures only the owner (root) can modify the keyring directory.
- Prevents unauthorized users from tampering with trusted GPG keys used to verify software packages.
- Ubuntu 24.04 and later recommend storing GPG keys in
/etc/apt/keyrings/
instead of the older/etc/apt/trusted.gpg
for better security.
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo tee /etc/apt/keyrings/docker.asc > /dev/null
Breaking The Three Parts of This Command Down:
1 curl -fsSL https://download.docker.com/linux/ubuntu/gpg
curl
→ A tool to download files from the internet.-f
→ Fails silently if the URL is incorrect (avoids downloading error messages).-s
→ Runs in silent mode (hides progress output).-S
→ Shows errors (only if they occur, making troubleshooting easier).-L
→ Follows redirects (in case the URL redirects to another location).https://download.docker.com/linux/ubuntu/gpg
→ The URL to Docker’s official GPG key.
What this does:
Downloads Docker’s GPG key, which is used to verify the authenticity of Docker packages.
2️ | sudo tee /etc/apt/keyrings/docker.asc
|
→ Pipes (redirects) the output ofcurl
to thetee
command.sudo
→ Runs the command as root (needed to write to system directories).tee /etc/apt/keyrings/docker.asc
→tee
writes the Docker GPG key into/etc/apt/keyrings/docker.asc
.- This file will later be used to verify that Docker packages are signed and authentic before installing them.
3 > /dev/null
>
redirects output somewhere else./dev/null
is a special “trash” file in Linux that discards anything written to it.
sudo chmod a+r /etc/apt/keyrings/docker.asc
Breaking It Down:
sudo
→ Runs the command with superuser (root) privileges.chmod
→ Changes file permissions.a
→ Stands for “all users” (owner, group, and others).+r
→ Adds read permission (so the file can be read by everyone)./etc/apt/keyrings/docker.asc
This is the GPG key file used to verify Docker packages when installing/updating viaapt
.
What this does:
1️ Allows the System to Use the Key
- When
apt
installs or updates Docker, it checks package signatures using this GPG key. - Without read access,
apt
might fail to verify Docker’s authenticity, causing errors.
2 Prevents Unauthorized Modifications
- The file remains protected (only root can modify it), but now all users can read it.
- This ensures that system processes and normal users can verify packages but not modify the key.
3️ Follows Ubuntu’s New Security Guidelines
- Older versions stored GPG keys in
/etc/apt/trusted.gpg
, which gave all keys full system-wide trust (less secure). - Newer Ubuntu releases use
/etc/apt/keyrings/
, where each key is isolated and explicitly trusted only for its repository.
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Breaking The Three Parts of This Command Down:
1️ echo "deb [...] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
echo
→ Outputs the text inside quotes."deb [...] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
→
This is a software repository entry in Debian/Ubuntu format.
What’s inside the deb [...]
line?
deb
→ Tellsapt
this is a binary package repository (not source code).[arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc]
arch=$(dpkg --print-architecture)
→ Detects your system architecture (amd64
,arm64
, etc.), ensuring you install the correct version.signed-by=/etc/apt/keyrings/docker.asc
→ Uses Docker’s GPG key (previously downloaded) to verify package authenticity.
https://download.docker.com/linux/ubuntu
→ The URL of Docker’s official repository.$(lsb_release -cs)
→ Dynamically inserts your Ubuntu codename (e.g.,noble
for 24.04), ensuring compatibility.stable
→ Installs the stable version of Docker (instead of edge/testing builds).
2️ | sudo tee /etc/apt/sources.list.d/docker.list
|
→ Pipes (echo
output) totee
, which writes it to a file.sudo
→ Runs with root privileges (since/etc/apt/sources.list.d/
requires admin access).tee /etc/apt/sources.list.d/docker.list
→ Saves the repository entry into/etc/apt/sources.list.d/docker.list
.
3️ > /dev/null
- Discards the output from
tee
, keeping the terminal clean.
Update your apt repositories:
sudo apt update
3. Install Docker
To install Docker (The following command will also install the needed dependencies):
sudo apt install -y docker-ce
To ensure Docker starts when the system boots:
sudo systemctl enable --now docker
Once installed and enabled, verify that Docker is running:
sudo docker ps
If docker is running you should see the following after running docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
With nothing showing under these headers.
🔒 Security Step: Prevent Unauthorized Docker Access
By default, Docker runs as root, which is a security risk. A safer approach is to create a dedicated user group:
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
After running these commands, you can run Docker without sudo:
docker run hello-world
4. Configure Docker for Better Security
A default Docker installation exposes certain risks. Let’s harden it.
Enable AppArmor
Ubuntu ships with AppArmor, a security module that restricts what Docker containers can access.
Check if it’s enabled:
sudo aa-status
If not, enable it with:
sudo systemctl enable --now apparmor
Disable Containers from Getting Root Privileges
By default, containers can run with elevated privileges. Restrict this with user namespaces:
TL;DR Cut & Paste These Commands:
sudo mkdir -p /etc/systemd/system/docker.service.d
echo -e "[Service]\nExecStart=\nExecStart=/usr/bin/dockerd --userns-remap=default" | sudo tee /etc/systemd/system/docker.service.d/override.conf
sudo systemctl daemon-reload
sudo systemctl restart docker
Breakdown of These Commands:
Create a Configuration Directory for Docker
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo
→ Runs the command as root (required for modifying system settings).mkdir -p
→ Creates a directory if it doesn’t already exist (-p
ensures no error if the directory exists)./etc/systemd/system/docker.service.d
→ This is where custom systemd overrides for Docker are stored.
Why?
This ensures we have a place to store a custom configuration for the Docker service without modifying the main Docker service file.
Create an Override File to Enable User Namespace Remapping
echo -e "[Service]\nExecStart=\nExecStart=/usr/bin/dockerd --userns-remap=default" | sudo tee /etc/systemd/system/docker.service.d/override.conf
echo -e "[Service]\nExecStart=\nExecStart=/usr/bin/dockerd --userns-remap=default"
→- Creates a custom systemd service override for Docker.
ExecStart=
(empty) clears the previous ExecStart setting from the default Docker service.ExecStart=/usr/bin/dockerd --userns-remap=default
replaces it with a new one that enables user namespace remapping.
| sudo tee /etc/systemd/system/docker.service.d/override.conf
→- Pipes the output (
|
) totee
, which writes it into the override file at/etc/systemd/system/docker.service.d/override.conf
. sudo
ensures root access for writing the file.
- Pipes the output (
Why?
- User namespace remapping (
--userns-remap=default
) makes Docker containers run as an unprivileged user instead of root. - This mitigates risks if a container is compromised—it won’t have full root access on the host.
Reload systemd
to Apply the Changes
sudo systemctl daemon-reload
sudo
→ Runs as root.systemctl daemon-reload
→ Reloads systemd so it recognizes the new Docker service override.
Why?
Without this, systemd
won’t detect the new override.conf
file.
Restart Docker to Apply the New Configuration
sudo systemctl restart docker
sudo
→ Runs as root.systemctl restart docker
→ Restarts Docker so it runs with the new--userns-remap=default
setting.
Why?
- This applies the security changes without rebooting the system.
- From now on, Docker containers will run as an unprivileged user instead of root.
Wrapping Up
Docker is a powerful tool for running apps on your Ubuntu 24.04 server, but an insecure setup can put your system at risk. By following this guide, you now have Docker installed correctly—with some security mitigations in place.
Want to take security even further? Consider ufw and/or fail2ban for added protection.
This sets us up for deploying Sonarr and Radarr services in the next posts.