LochStudios  /  Help Centre  /  VPS & Linux  /  Install Docker and Docker Compose

Install Docker and Docker Compose

Install Docker Engine and the Compose plugin on your LochStudios KVM VPS (Ubuntu or Debian) so you can run containers.

Updated

Docker packages an app and its dependencies into a container. The Compose plugin (docker compose) starts a group of those containers from one YAML file. This article installs Docker Engine from Docker's official repository on a LochStudios KVM VPS.

Shared hosting (cPanel) is a different product. You cannot run Docker there. You need a VPS.

The IPv4, username, password, and an out-of-band console sit on that server in the portal. Sign in at the portal, open the VPS service, and copy the login from there.

Before you start

  1. Sign in at the portal, open the VPS service, and keep that page open.
  2. Connect with a sudo user, or root on a fresh box. See Connect to your VPS via SSH from macOS or Linux or from Windows.
  3. Prefer a sudo user for daily work: First steps on a new VPS.
  4. Use Ubuntu 22.04 or 24.04, or Debian 12. If you are on AlmaLinux or Rocky Linux, skip to AlmaLinux or Rocky Linux.

If SSH from your PC will not connect, open the console on the same service. That session does not need port 22 from your network.

If you are logged in as root, omit sudo from the commands below.

Ubuntu or Debian

1. Update packages

sudo apt update
sudo apt upgrade -y

2. Remove older Docker packages (if any)

Ubuntu and Debian ship docker.io in their own repos. Remove those so they do not fight Docker Engine:

sudo apt remove -y docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc

It is fine if apt says some of those packages were not installed.

3. Install the tools the repo needs

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

4. Add Docker's official repository

Ubuntu:

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
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

Debian:

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
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Use the Ubuntu block on Ubuntu and the Debian block on Debian. Mixing the two leaves apt unable to find packages.

5. Install Docker Engine and Compose

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

That is Docker Engine, the CLI, containerd, Buildx, and Compose v2 (docker compose, two words). You do not need a separate docker-compose binary.

AlmaLinux or Rocky Linux

sudo dnf -y install 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-buildx-plugin docker-compose-plugin

Docker publishes that repo for RHEL-compatible systems. If dnf config-manager is missing, install dnf-plugins-core first, then retry.

Start Docker and confirm it works

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

You should see version strings and a Hello from Docker! message. The test container is removed afterwards (--rm).

Check the service if a command fails:

sudo systemctl status docker

You want active (running).

Optional: run Docker without sudo

sudo usermod -aG docker $USER

Then log out of SSH and log back in. Group membership only applies on a new session. After that, docker and docker compose work without sudo.

Do not skip the reconnect. newgrp docker only fixes the current shell.

Anyone in the docker group can become root on the box. Only add accounts you trust. Prefer SSH keys: Secure SSH with key-based authentication and disable password login.

A first Compose file

Create a directory and a compose.yaml:

mkdir -p ~/docker-demo
cd ~/docker-demo
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    restart: unless-stopped
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: change-me
    volumes:
      - db_data:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  db_data:

The database has no ports: line, so Postgres is only reachable from other containers on this Compose network, not from the internet. Change change-me before you store anything real.

Start it:

docker compose up -d

Watch logs:

docker compose logs -f

Stop and remove the containers (the named volume stays):

docker compose down

Add -v only when you intend to delete the volume and the data in it.

Publish ports on the VPS

A ports: mapping such as "80:80" listens on the VPS IPv4. UFW still has to allow that traffic. On our VPS you run UFW yourself. See Set up a UFW firewall on Ubuntu.

For a public website:

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Always allow SSH (port 22) before you enable UFW. If a rule locks you out, open the console on the VPS service in the portal.

Do not publish a database port (5432, 3306) to the whole internet. If another machine must connect, pin the source IPv4 in UFW instead of ports: "5432:5432" plus a wide allow.

Point the domain at this VPS IPv4 in the portal under Domains → the domain → DNS. AtlasDNS is the default. See Point your domain at your hosting. For TLS on the host, use Get a Free SSL Certificate with Certbot, or terminate TLS in a reverse-proxy container.

Everyday commands

  • Images: docker pull nginx:latest before you recreate a service.
  • Status: docker compose ps
  • Logs: docker compose logs -f web
  • Restart one service: docker compose up -d web
  • Disk: docker system df, then docker image prune and docker container prune for unused objects. docker system prune -a also deletes unused images. Read the prompt.
  • Data: keep databases and uploads in named volumes or a bind mount. Files written only inside the container filesystem disappear when the container is removed.

Smaller VPS plans fill RAM quickly with several containers. Add overflow with Add Swap Space to Your VPS and watch usage with Monitor Server Resources.

Keep the host patched: Enable Automatic Security Updates. That updates Ubuntu or Debian packages, not the images you pulled. Rebuild or docker pull those yourself.

If something goes wrong

Cannot connect to the Docker daemon

sudo systemctl start docker
sudo systemctl status docker

If you dropped sudo after adding the docker group, log out and SSH in again.

permission denied while talking to the socket

You are not in the docker group yet, or this login started before usermod. Run the group command again, then reconnect.

apt cannot find docker-ce

You used the Ubuntu repo on Debian, or the other way around. Remove /etc/apt/sources.list.d/docker.list, add the matching block from above, then sudo apt update.

The site is not reachable after compose up

  • Confirm the container is up: docker compose ps
  • Confirm it is listening: sudo ss -tlnp
  • Confirm UFW: sudo ufw status verbose
  • Confirm the IPv4 you are hitting is the one on the VPS in the portal
  • Confirm the domain A record, if you are using a name

You cannot SSH after opening UFW

Open the console on the VPS service in the portal, then:

sudo ufw allow 22/tcp
sudo ufw status verbose

Still stuck? Open a support ticket. Tell us the VPS service, the IPv4, the OS, and the command or error you saw. Do not send the password in the ticket.

What to do next

Need a VPS first? See VPS.

Unsure about a step? Open a support ticket and we will walk through it with you.


Was this article helpful?

← Back to VPS & Linux