How to install Docker on Ubuntu the official way
Docker packages an application and everything it needs into a container, so it runs the same way everywhere. On a VPS, that means you can run a database, a web app or a bot with one command, without installing a pile of dependencies on the host. Ubuntu's own package for Docker is often older than Docker's, so it is best to install from Docker's official repository. Here is how.
Before you start
- An Ubuntu server you can reach over SSH, with a user who has sudo rights. See How to create a non-root user with sudo.
- A basic firewall in place. Read the note about Docker and firewalls below before opening anything to the internet.
- Enough memory and disk. Docker itself is light, but images and containers use space. See What the CPU, memory and disk numbers on your server mean.
Remove old packages
If an older Docker or a distribution-supplied version was installed, remove it first:
sudo apt remove docker.io docker-doc docker-compose podman-docker containerd runc
If none are installed, it simply says so. Your existing images and containers are not deleted by this.
Add Docker's repository
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
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
Then add the repository, as a single command:
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
sudo apt update
Install the packages
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
This installs the Docker engine, its command line tool and Compose as a plugin. Check it works:
sudo systemctl status docker
sudo docker run hello-world
The second command downloads a tiny test image and prints a short welcome message, which proves the engine can pull and run containers.
Using Docker without typing sudo
By default, only root can talk to Docker. You can add your user to the docker group:
sudo usermod -aG docker $USER
Log out and back in for it to take effect. Understand what this does: anyone in the docker group can run containers that mount the whole file system, which is effectively root access. Add only people you trust as much as an administrator.
Everyday commands
| Command | What it does |
|---|---|
docker ps | Show running containers |
docker ps -a | Show all containers, including stopped |
docker images | List downloaded images |
docker logs name | Show a container's output |
docker logs -f name | Follow the output live |
docker stop name and docker start name | Stop and start a container |
docker rm name | Delete a stopped container |
docker system prune | Remove unused data, to free space |
A small example, running a web server in the background and publishing a port:
docker run -d --name web --restart unless-stopped -p 8080:80 nginx
-d runs it in the background, --restart unless-stopped brings it back after a reboot or crash, and -p 8080:80 connects port 8080 on the server to port 80 inside the container.
Docker and your firewall
This is the most important warning. When you publish a port with -p, Docker adds its own firewall rules that bypass UFW. So a port that UFW says is closed can still be open to the whole internet. Two ways to stay safe:
- Publish only to the local machine when the service should not be public:
-p 127.0.0.1:8080:80. Then put a reverse proxy such as nginx in front, as in Run a Node.js app on your VPS with PM2 and nginx. - Check what is actually reachable from outside, rather than trusting the firewall's status. See Set up a firewall on your VPS with UFW.
Keep data safe
Containers are disposable, so their inner storage disappears when the container is removed. Keep anything valuable in a volume or a mounted folder on the host:
docker run -d --name db -v dbdata:/var/lib/mysql ...
Back those folders up. See How to back up your VPS with rsync.
Cleaning up
Images and stopped containers pile up. If the disk fills, run docker system df to see the cause, then docker system prune to remove unused containers, networks and dangling images. Add -a only when you are sure you do not need the unused images.
Next steps
Running several containers together is easier with Compose, described in Docker Compose basics for small projects. And keep the system updated, as in Turn on automatic security updates.
Still stuck? Open a ticket on Discord - run /ticket in any channel, pick a department, and include your Server ID or Invoice ID so we can jump straight in.