In this tutorial, you’ll install Docker Engine on a Raff Ubuntu 24.04 VM, add Docker’s official APT repository, install the Docker Compose plugin, verify the installation with hello-world, and run a practical Nginx container test.
Docker is the standard platform for building, shipping, and running applications inside containers. Containers isolate applications and their dependencies while sharing the host operating system kernel, which makes deployments faster, more portable, and easier to reproduce across development, staging, and production environments.
Raff Technologies runs over 10,000 VMs across its compute platform in Vint Hill, Virginia, on AMD EPYC hardware with NVMe storage.
Prerequisites:
- A Raff Ubuntu 24.04 VM
- SSH access with sudo privileges
- Ports
80/tcpand8080/tcpavailable for the test container step - A clean Ubuntu environment without conflicting Docker packages installed
This tutorial was tested on a Raff VM with 2 vCPU, 2 GB RAM, running Ubuntu 24.04.4 LTS.
Tested on Raff infrastructure by Aybars Altınyay, platform engineer and technical writer at Raff Technologies.
Step 1 — Update Ubuntu and install prerequisites
Update the package index and install the packages required to add Docker’s official APT repository.
sudo apt update sudo env DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt upgrade -y \ -o Dpkg::Options::=--force-confdef \ -o Dpkg::Options::=--force-confold sudo apt install -y ca-certificates curl gnupg lsb-release ufw
📌 Note: If Ubuntu asks what to do with a modified
/etc/ssh/sshd_configfile, select keep the local version currently installed. This preserves your current SSH login configuration.
Verify the Ubuntu version:
lsb_release -ds
Expected output:
Ubuntu 24.04.4 LTS
Minor Ubuntu 24.04 point releases are acceptable.
Step 2 — Remove conflicting Docker packages
Before installing Docker from the official Docker repository, remove conflicting packages that may come from Ubuntu’s default repositories or previous installations.
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt remove -y "$pkg" 2>/dev/null || true done
This command is safe on a fresh VM. If none of the packages are installed, APT simply reports that there is nothing to remove.
Verify that the docker command is not already installed:
docker --version
Expected output on a fresh VM:
Command 'docker' not found
If Docker is already installed and you are intentionally upgrading an existing server, review your current containers and volumes before continuing.
Step 3 — Add Docker’s official APT repository
Create the APT keyring directory:
sudo install -m 0755 -d /etc/apt/keyrings
Download Docker’s official GPG key:
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc
Set the correct permissions:
sudo chmod a+r /etc/apt/keyrings/docker.asc
Add Docker’s APT repository:
sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null <<EOF Types: deb URIs: https://download.docker.com/linux/ubuntu Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") Components: stable Architectures: $(dpkg --print-architecture) Signed-By: /etc/apt/keyrings/docker.asc EOF
Update the package index again:
sudo apt update
Verify that APT can see Docker’s repository:
apt-cache policy docker-ce | sed -n '1,12p'
Expected output includes:
docker-ce: Candidate: Version table:
The candidate version may change over time as Docker releases new stable versions.
Step 4 — Install Docker Engine and Docker Compose
Install Docker Engine, the Docker CLI, containerd, Buildx, and the Docker Compose plugin.
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Verify Docker Engine:
docker --version
Expected output:
Docker version 29.x.x, build xxxxxxx
Verify Docker Compose:
docker compose version
Expected output:
Docker Compose version v5.x.x
The exact Docker and Docker Compose versions may differ depending on the current stable packages available from Docker’s repository.
Step 5 — Verify the Docker service
Docker should start automatically after installation. Check that the service is active:
systemctl is-active docker
Expected output:
active
View the full service status:
sudo systemctl status docker
Expected output includes:
Active: active (running)
Common Docker service commands:
sudo systemctl stop docker sudo systemctl start docker sudo systemctl restart docker sudo systemctl status docker sudo systemctl enable docker
Verify that Docker can communicate with the daemon:
sudo docker ps
Expected output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
An empty container list is expected on a fresh VM.
Step 6 — Run the Docker hello-world test
Run the official hello-world test container.
sudo docker run --rm hello-world
Expected output includes:
Hello from Docker! This message shows that your installation appears to be working correctly.
This confirms that Docker can pull an image, create a container, run it, and print output successfully.
Verify that no hello-world container remains after using --rm:
sudo docker ps -a
Expected output does not need to show a hello-world container.
Step 7 — Run a practical test with Nginx
Run a temporary Nginx container and map it to port 8080 on the VM.
sudo ufw allow 8080/tcp sudo docker rm -f test-nginx 2>/dev/null || true sudo docker run -d --name test-nginx -p 8080:80 nginx
Verify that the container is running:
sudo docker ps
Expected output includes:
test-nginx Up 0.0.0.0:8080->80/tcp
Test the Nginx container locally:
curl -I http://localhost:8080
Expected output includes:
HTTP/1.1 200 OK Server: nginx
Find your VM’s public IP address:
curl -4 icanhazip.com
Open your browser and visit:
http://your_server_ip:8080
Visible state check:
The browser shows the default Nginx welcome page. The page is served from a Docker container mapped to port 8080. The URL uses http://your_server_ip:8080.

The test is successful when the browser shows the Nginx welcome page and curl -I http://localhost:8080 returns HTTP/1.1 200 OK.
📌 Note: The browser may show “Not secure” because this test uses plain HTTP on port
8080. That is expected for this verification step.
Step 8 — Configure non-root Docker access
By default, Docker commands require sudo. If this is your personal VM and you want to run Docker commands without sudo, add your user to the docker group.
sudo usermod -aG docker "$USER"
Apply the group change in the current shell:
newgrp docker
Verify that Docker runs without sudo:
docker ps
Expected output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
⚠️ Warning: Membership in the
dockergroup grants root-equivalent access on the host. Only add trusted users to this group. On shared servers, keep usingsudo dockerinstead.
If you are connected as root, this step is optional because the root user already has permission to run Docker.
Step 9 — Verify the complete Docker installation
Run a final verification sequence.
echo "Checking Docker version:" docker --version || sudo docker --version echo "Checking Docker Compose version:" docker compose version || sudo docker compose version echo "Checking Docker service:" systemctl is-active docker echo "Checking running containers:" sudo docker ps echo "Checking Nginx test container:" curl -I http://localhost:8080
Expected output includes:
Docker version Docker Compose version active test-nginx HTTP/1.1 200 OK
The Docker installation is complete when Docker Engine is installed, Docker Compose is available, the Docker service is active, hello-world runs successfully, and the Nginx test container serves a page on port 8080.
Cleanup (Optional)
Use this section to remove only the temporary Nginx test container and close the test port.
sudo docker stop test-nginx sudo docker rm test-nginx sudo ufw delete allow 8080/tcp
Verify cleanup:
sudo docker ps sudo ufw status numbered
Expected output no longer shows the test-nginx container or the 8080/tcp firewall rule.
To remove the hello-world image and Nginx image as well:
sudo docker image rm hello-world nginx
📌 Note: Do not remove Docker itself if you plan to use this VM for containerized applications.
Troubleshooting
docker: command not found
Cause: Docker Engine is not installed, or the installation did not complete.
Fix:
apt-cache policy docker-ce sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker --version
Expected output includes a Docker version.
Cannot connect to the Docker daemon
Cause: The Docker service is not running, or your user does not have permission to access Docker.
Fix:
systemctl is-active docker sudo systemctl start docker sudo docker ps
If you configured non-root access, log out and back in or run:
newgrp docker docker ps
The Nginx test page does not open in the browser
Cause: The container is not running, port 8080 is blocked, or the wrong IP address is being used.
Fix:
sudo docker ps sudo ufw status numbered curl -4 icanhazip.com curl -I http://localhost:8080
Expected output includes:
test-nginx 8080/tcp ALLOW IN HTTP/1.1 200 OK
Port 8080 is already in use
Cause: Another process or container is already using port 8080.
Fix:
sudo ss -tulpn | grep ':8080' sudo docker ps
If another test container is using the port, remove it:
sudo docker rm -f test-nginx
Then start the Nginx test container again:
sudo docker run -d --name test-nginx -p 8080:80 nginx
Docker Compose is not available
Cause: The Docker Compose plugin was not installed.
Fix:
sudo apt install -y docker-compose-plugin docker compose version
Expected output includes:
Docker Compose version
UFW blocks container traffic
Cause: Port 8080 is not allowed through UFW.
Fix:
sudo ufw allow 8080/tcp sudo ufw status numbered
Expected output includes:
8080/tcp ALLOW IN
After testing, close the port again:
sudo ufw delete allow 8080/tcp
Conclusion
You have installed Docker Engine on a Raff Ubuntu 24.04 VM from Docker’s official APT repository, installed the Docker Compose plugin, verified Docker with hello-world, and confirmed a practical Nginx container works through port 8080.
From here, you can deploy multi-container applications with Docker Compose, self-host developer tools, run databases, or deploy web applications behind Nginx or Caddy. If you haven’t deployed your Raff VM yet, you can spin one up in 60 seconds at rafftechnologies.com.
Next: Deploy Uptime Kuma with Docker on Ubuntu 24.04 Related: Install Nginx on Ubuntu 24.04 Guide: Automate Server Backups with Cron and Rsync on Ubuntu 24.04
