Home > Blog > Engineering > Installing Docker on VPS with Ubuntu or Debian in 2026

Installing Docker on VPS with Ubuntu or Debian in 2026

Deploying containerised applications on a VPS with Docker Engine and Compose.
Sharma bal

Sharma bal

Jul 11, 2024
0 Comments
7 minutes read

Table of content

  1. Step 1: Check the VPS before installing packages
  2. Step 2: Add the official repository for your distribution
  3. Step 3: Install Docker Engine and Compose
  4. Step 4: Verify the daemon and a test container
  5. Step 5: Keep administrative access deliberate
  6. Step 6: Run a small service with Compose
  7. Step 7: Decide which ports should be public
  8. Step 8: Preserve data and plan updates
  9. Troubleshooting installation and first startup

Installing Docker on VPS starts with Docker Engine and the Compose plugin. On a fresh Ubuntu or Debian server, you can install both from Docker’s official apt repository, verify the daemon, then launch a small web service. The example below keeps that service accessible only from the VPS until you deliberately change its exposure.

This guide targets Ubuntu 24.04 LTS and Debian 13 with systemd, using a non-root account with sudo access. It covers a new rootful Docker Engine installation, not Docker Desktop or an upgrade of an existing container platform. For other releases, check Docker’s supported operating systems before copying the commands.

Step 1: Check the VPS before installing packages

Confirm the operating system and architecture, then look at available memory and disk space:

cat /etc/os-release
dpkg --print-architecture
free -h
df -h /

The application will determine most of the resource requirement. Image downloads, build caches and logs also consume storage. A small demonstration is not a capacity test for the production stack.

Use a VPS that allows Docker and provides the necessary kernel capabilities. If it is itself a restricted container, ask the provider about support. Keep SSH access working and retain access to the provider’s console before making changes to the host.

Check whether a container runtime is already installed:

dpkg -l | grep -E 'docker|containerd|runc|podman'

No matches are normal on a clean server. Existing distribution Docker packages, or separately installed containerd and runc packages, can conflict with Docker’s packages. If you find them, follow the conflict-removal section of the official instructions for your distribution after identifying any workloads that depend on them. Do not remove a runtime from a working server as though it were an unused prerequisite.

Update the fresh host and install the download prerequisites. Review any proposed package changes; reboot if the update requires it, then reconnect before continuing.

sudo apt update
sudo apt upgrade
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings

Step 2: Add the official repository for your distribution

Run only the block matching your operating system. Each block installs Docker’s signing key and writes an apt source file. The system architecture and release codename are read from the host.

Ubuntu 24.04 LTS

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
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

Debian 13

sudo curl -fsSL https://download.docker.com/linux/debian/gpg \
  -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

Stop if the key download fails. Check connectivity and the command rather than bypassing signature verification. Do not reuse an Ubuntu repository on Debian or substitute a different release just to silence an apt error.delve into the exciting world of Docker installation methods for different Managed VPS providers!

Step 3: Install Docker Engine and Compose

Both distributions use the following package command after their repository is configured:

sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

This installs Engine, its command-line client, the bundled runtime, Buildx and Compose. The Compose command is docker compose, with a space. An old tutorial using a separately downloaded docker-compose binary describes a different installation path.

Step 4: Verify the daemon and a test container

sudo systemctl enable --now docker
sudo systemctl status docker --no-pager
sudo docker version
sudo docker compose version
sudo docker run --rm hello-world

Look for an active Docker service and both client and server information in the version output. The hello-world container should print its confirmation and exit. The –rm option removes that stopped test container, while its downloaded image remains cached.

This checks the runtime and image retrieval. It does not establish that a public application is reachable, correctly configured or ready for production.

Step 5: Keep administrative access deliberate

The examples continue to use sudo. Adding an account to the docker group allows it to control the rootful daemon, which effectively gives it root-level capabilities. It is not an ordinary convenience permission to grant every server user.

Do not make the Docker socket world-writable to fix a permission error. Keep daemon access restricted to administrators. Rootless Docker is a separate deployment option with its own prerequisites and behaviour; follow its documentation if that is the model you need.

Step 6: Run a small service with Compose

Create a project directory and a static page:

mkdir -p ~/docker-demo/html
cd ~/docker-demo
printf ‘%s\n’ ‘<h1>Docker is serving this page</h1>’ > html/index.html

Save the following as compose.yaml inside that directory. Preserve the indentation.

services:
  web:
    image: nginx:stable-alpine
    ports:
      - "127.0.0.1:8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
    restart: unless-stopped
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

The host’s html directory supplies the page, mounted read-only inside the container. Port 8080 is bound to the VPS loopback address. Log rotation limits the space consumed by this service’s Docker logs.

The image tag is convenient for this demonstration, but it can change. For production, record a tested version or digest and maintain an update process. A digest makes the selected image reproducible; it does not install future fixes automatically.

Validate the Compose file, start the service and request the page from the VPS:

sudo docker compose config --quiet
sudo docker compose up -d
sudo docker compose ps
curl -fsS http://127.0.0.1:8080

You should see the HTML created earlier. If not, inspect the service logs:

sudo docker compose logs --tail=50 web

To view the page from your computer without publishing the port, open a separate local terminal and run this command, replacing admin and SERVER_IP with your SSH account and VPS address:

ssh -N -L 8080:127.0.0.1:8080 admin@SERVER_IP

Keep that terminal open and visit http://127.0.0.1:8080 in your local browser. If your computer already uses port 8080, change the first 8080 in the SSH command to 8081 and browse to that port instead.

Step 7: Decide which ports should be public

A mapping such as 8080:80 normally publishes on the host’s network interfaces. The explicit 127.0.0.1:8080:80 mapping above limits access to the host. Do not remove that address unless public exposure is intentional.

Docker manages packet-filtering rules, and published container traffic can bypass the restrictions you expect from UFW. Check Docker’s firewall documentation for the active backend and verify access from another machine. A provider firewall adds another layer, but its settings do not automatically configure Linux rules.

For a public website, plan the domain, HTTPS termination and the ports the reverse proxy needs. Keep databases and management interfaces off public ports unless the architecture explicitly requires access and protects it. Containers can communicate over an internal Docker network without publishing every service.

Step 8: Preserve data and plan updates

The demonstration’s page survives replacement of its container because it lives in the host directory. Stateful applications need an equivalent plan using suitable volumes or bind mounts. A database also needs a consistent backup; copying files while it writes may not produce a recoverable database.

From the demo directory, this stops and removes the Compose containers and network:

sudo docker compose down

It leaves the html directory intact. In other projects, take care with down -v, which removes eligible volumes. A volume attached to a VPS is still lost if the underlying storage is lost, so keep backups in a separate failure domain and test restoration.

Update host packages and application images as separate maintenance tasks. Check release notes, back up state and verify the application after replacement. Major database upgrades may require migration steps beyond choosing a new image tag.

Troubleshooting installation and first startup

Symptom Check first Next action
No installation candidate Repository file and apt update output Confirm the distribution, codename and architecture
Cannot connect to daemon Docker service status Read journalctl logs before changing settings
Socket permission denied Whether sudo was used Correct access without opening socket permissions
Port already allocated Existing host listeners Choose a free port or resolve the intended conflict
Image pull fails DNS, network access and registry response Distinguish connectivity from authentication or rate limits
Container starts then exits Application logs and configuration Correct the service error before repeatedly restarting it

For daemon and port investigations:

sudo journalctl -u docker -n 100 --no-pager
sudo ss -lntup

Choose the VPS around the application

For a Hostomize deployment, confirm the available Linux image and Docker support, then size the plan around the services you will run. Storage growth, backups and application administration remain part of the deployment after Docker is installed.

Frequently asked questions

Can Docker run on any VPS?

The provider and guest environment must support the necessary Linux features. A conventional compatible Linux VM is different from a restricted container-based plan. Confirm support for the plan you intend to use.

How much RAM is needed for installing Docker on VPS?

Size the server for its applications, builds and peak usage, with space for the operating system. A successful hello-world run says little about the memory needed for a database or collaboration service.

Should I use the convenience installation script?

Docker documents it mainly for testing and development. The repository method above makes the package source and installed components explicit and is a better starting point for a maintained server.

Is Docker Desktop required on the VPS?

No. This guide installs Docker Engine and the Compose plugin on Linux. Docker Desktop is not required for this server workflow.

Comments

Get your SSD VPS

Starting from $5.06/month.