By the end of this guide you will have Docker Engine and the Docker CLI installed on Ubuntu 24.04, configured to run without sudo, and verified with a live container. You will also have the daemon set to start on boot via systemd. No Docker Desktop, no Snap package — just the upstream Docker Engine that actually works in production.
Prerequisites
- A fresh or existing Ubuntu 24.04 LTS server (amd64 or arm64)
- A non-root user with
sudoprivileges - Outbound internet access on port 443
- At least 2 GB of disk space free on
/var
Step 1 — Remove Conflicting Packages
Ubuntu 24.04 ships with docker.io and related shims that conflict with the upstream Docker Engine. Remove them first.
sudo apt-get remove -y docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc
This command uninstalls every conflicting package. apt-get will print "Package X is not installed" for anything already absent — that is expected.
Step 2 — Update the Package Index and Install Dependencies
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
ca-certificates and curl are needed to fetch the Docker GPG key over HTTPS. gnupg is required to import and verify it.
Step 3 — Add Docker's Official GPG Key
- Create the keyring directory:
sudo install -m 0755 -d /etc/apt/keyrings
- Download and store the key:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
- Set correct permissions so
aptcan read the key:
sudo chmod a+r /etc/apt/keyrings/docker.gpg
These three commands create a dedicated keyring file for Docker at /etc/apt/keyrings/docker.gpg with world-readable permissions.
Step 4 — Add the Docker APT Repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
This writes a single-line APT source entry to /etc/apt/sources.list.d/docker.list. The $(dpkg --print-architecture) substitution pins the repo to your CPU architecture (amd64 or arm64). The $VERSION_CODENAME substitution resolves to noble on Ubuntu 24.04.
Verify the file was written correctly:
cat /etc/apt/sources.list.d/docker.list
Expected output:
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable
Step 5 — Install Docker Engine
- Refresh the package index to pick up the new repo:
sudo apt-get update
- Install Docker Engine, the CLI, containerd, and the Compose plugin:
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
| Package | Purpose |
|---|---|
docker-ce |
Docker Engine daemon |
docker-ce-cli |
docker command-line client |
containerd.io |
Container runtime |
docker-buildx-plugin |
Extended build capabilities |
docker-compose-plugin |
docker compose subcommand |
This is the full production stack. Skipping any of these packages will leave you with a partial install.
Step 6 — Enable and Start the Docker Daemon
sudo systemctl enable --now docker
The --now flag both enables the docker unit for automatic start on boot and starts it immediately in a single command. The systemd unit name is docker.service.
Check the daemon status:
sudo systemctl status docker
Expected output (truncated):
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: enabled)
Active: active (running) since ...
If the status shows active (running), the daemon is up.
Step 7 — Run Docker Without sudo
By default, the Docker socket is owned by the docker group. Add your user to that group so you can run docker commands without sudo.
- Add your current user to the
dockergroup:
sudo usermod -aG docker $USER
- Apply the new group membership without logging out:
newgrp docker
newgrp docker starts a new shell session with the docker group active. In automated provisioning scripts, prefer logging out and back in instead.
Security note: Any user in the
dockergroup has effective root access to the host via volume mounts. Only add trusted users.
Step 8 — Configure the Docker Daemon (Optional but Recommended)
Create /etc/docker/daemon.json to set a log rotation policy and a sane storage driver. Without log rotation, container logs will fill your disk on a busy server.
sudo tee /etc/docker/daemon.json > /dev/null <<EOF
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2"
}
EOF
Reload the daemon to apply the configuration:
sudo systemctl reload docker
This caps each container's log at 10 MB with 3 rotated files — 30 MB maximum per container. overlay2 is the correct storage driver for Ubuntu 24.04 with ext4 or XFS.
Verify It Works
Run the official smoke-test image:
docker run --rm hello-world
Expected output:
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
Verify the Docker Compose plugin is available:
docker compose version
Expected output:
Docker Compose version v2.27.0
(The exact version number will vary; any v2.x output confirms the plugin is installed.)
Verify the daemon configuration was applied:
docker info | grep -E 'Storage Driver|Logging Driver'
Expected output:
Storage Driver: overlay2
Logging Driver: json-file
Troubleshooting
docker: permission denied while trying to connect to the Docker daemon socket
Your user is not yet in the docker group, or the group change has not taken effect. Run newgrp docker or log out and back in. Confirm with groups — you should see docker in the list.
**apt-get update fails with NO_PUBKEY or GPG error** The key at /etc/apt/keyrings/docker.gpg` was not written correctly. Delete it and repeat Step 3:
sudo rm /etc/apt/keyrings/docker.gpg
Then re-run the curl | gpg command from Step 3.
docker.service fails to start — containerd socket not found`
containerd may not have started. Run:
sudo systemctl status containerd
sudo systemctl start containerd
sudo systemctl restart docker
overlay2 not listed in docker info
Your kernel may lack the overlay module. Load it manually and verify:
sudo modprobe overlay
lsmod | grep overlay
If the module is absent, upgrade the kernel: sudo apt-get install -y linux-generic.
hello-world image pull times out
Check outbound connectivity: curl -I https://registry-1.docker.io. If you are behind a proxy, configure /etc/systemd/system/docker.service.d/http-proxy.conf with your proxy settings and reload the daemon.
daemon.json causes the daemon to fail on reload
Validate the JSON before applying:
python3 -m json.tool /etc/docker/daemon.json
A syntax error in daemon.json will prevent the daemon from starting. Fix the file and run sudo systemctl restart docker.
Next Steps
With Docker running on Ubuntu 24.04, you are ready to:
- Deploy a container in production — use
docker run -d --restart=unless-stoppedto keep services alive across reboots. - Set up Docker Compose projects — create a
compose.ymland manage multi-container stacks withdocker compose up -d. - Harden the daemon — enable user namespaces (
userns-remap) indaemon.jsonto isolate container root from host root. - Set up a private registry — run
registry:2as a container to cache images locally and cut egress costs on Hetzner or any metered VPS. - Monitor disk usage — schedule
docker system prune -fweekly via cron to reclaim space from dangling images and stopped containers.
This setup costs nothing beyond your existing VPS and runs reliably on a $4/month Hetzner CAX11 ARM instance.