How to Install Docker on Your VPS
Get Docker and Docker Compose running on Ubuntu, Debian, AlmaLinux, or Rocky, and launch your first container in about five minutes.

Docker packages an application and everything it depends on into a single image, so it runs the same way on your server as it did on your laptop. It is the fastest way to get most self-hosted software running without spending an afternoon on dependencies.
Before you start
You need SSH access to your VPS and a user with sudo. If you are still logging in as root, set up a real user account first. It takes a minute and you will want it.
Do not install Docker from your distribution's default repositories. Those packages are usually several versions behind and are missing the Compose plugin. Use Docker's official repository instead, which is what the steps below do.
Step 1: Install Docker
On Ubuntu or Debian, Docker's convenience script adds the official repository and installs everything in one go:
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
On AlmaLinux or Rocky, add the repository and install the packages directly:
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
Step 2: Start Docker and enable it at boot
On Ubuntu and Debian this already happened. On AlmaLinux and Rocky you need to do it yourself:
sudo systemctl enable --now docker
enable --now both starts the service and makes it come back automatically after a reboot. Skip it and your containers will not return after the next restart.
Step 3: Run Docker without sudo
By default every Docker command needs sudo. Add your user to the docker group to skip that:
sudo usermod -aG docker $USER
Log out and back in for the change to apply. Checking with groups in the same session will not show it.
Worth knowing: membership of the docker group is effectively root access, since a container can mount the host filesystem. Only add users you would give root to anyway.
Step 4: Check it works
docker run --rm hello-world
Docker pulls a tiny test image, runs it, prints a confirmation message, and, because of --rm, cleans up the container afterwards. If you see "Hello from Docker!", you are done installing.
Confirm Compose is there too:
docker compose version
That is docker compose as two words. The old docker-compose hyphenated command is a separate legacy tool, and most current guides assume the plugin version.
Step 5: Run something real
Compose describes your containers in a file instead of a long command line, which makes them easy to restart and easy to remember six months later.
Create a directory and a compose.yaml inside it:
mkdir ~/nginx-test && cd ~/nginx-test
nano compose.yaml
Paste this in:
services:
web:
image: nginx
ports:
- "80:80"
restart: unless-stopped
Start it:
docker compose up -d
-d runs it in the background. restart: unless-stopped brings the container back after a reboot or a crash, which is what you almost always want on a server.
Step 6: Open the port
Your container is listening, but the Virtualized network closes ports by default, so nothing reaches it yet.
In the client portal, open Services, then Firewall Manager. Select your IP, click New Rule, set the protocol to TCP, set the destination port to 80, tick Whitelist, and click Create Rule. Allow up to fifteen minutes for it to propagate, then visit your server's IP in a browser.
The commands you will actually use
docker ps: what is running right nowdocker ps -a: including stopped containersdocker compose logs -f: follow the logs of everything in the current directorydocker compose down: stop and remove the containersdocker compose pull && docker compose up -d: update to the latest imagesdocker system prune -a: reclaim disk from unused images and layers
That last one is worth remembering. Old images accumulate quietly, and a full disk is one of the more common ways a Docker host falls over.
If something goes wrong
"permission denied while trying to connect to the Docker daemon socket". You added yourself to the docker group but have not logged out and back in yet.
"port is already allocated". Something else is already using that port, often a distribution's own Nginx or Apache. Find it with sudo ss -tulpn | grep :80 and either stop it or map your container to a different port.
The container starts and immediately exits. The application inside crashed. docker compose logs will tell you why; the answer is usually a missing environment variable or a config file that is not mounted where the image expects it.