Linux VPS

Install Docker and Docker Compose on a Linux VPS

Install Docker Engine and the Compose plugin from Docker's own repository, run a first Compose project, cap log size and avoid exposing ports by accident.

IntermediateLinux server3 min read

Docker runs applications in containers, and Docker Compose describes a multi-container app in one file. Install them from Docker's official repository to get current versions; the distribution packages are often older.

1. Install on Ubuntu or Debian

Bash
sudo apt update
sudo apt install -y 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
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Debian 12: use the same commands but replace both linux/ubuntu URLs with linux/debian.

On AlmaLinux or Rocky Linux instead

Bash
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-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker

2. Check it works

Bash
sudo docker run --rm hello-world
docker compose version

3. Run Docker without sudo (optional)

Bash
sudo usermod -aG docker $USER

Log out and back in for it to apply.

Warning: Membership of the docker group is equivalent to root access on the server. Only add users you would trust with root.

4. Your first Compose project

Create a folder with a compose.yaml file:

YAML
services:
  web:
    image: nginx:stable
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
    volumes:
      - ./site:/usr/share/nginx/html:ro

Start, inspect and stop it:

Bash
docker compose up -d
docker compose ps
docker compose logs -f web
docker compose down

Keep ports private

Docker writes its own firewall rules, so a port published as "8080:80" is reachable from the internet even if UFW or firewalld does not allow it. Publish to 127.0.0.1 as in the example above, and expose the app through Nginx with HTTPS. See Install Nginx and Let's Encrypt for Nginx.

Stop logs from filling the disk

By default container logs grow without limit. Create /etc/docker/daemon.json:

JSON
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" }
}

Then sudo systemctl restart docker. The limit applies to containers created after the change, so recreate them with docker compose up -d --force-recreate.

Troubleshooting

  • permission denied while trying to connect to the Docker daemon socket: use sudo, or log out and back in after adding yourself to the docker group.
  • Port already allocated: another container or service uses it. Find it with sudo ss -tlnp | grep 8080.
  • Disk filling up: docker system df shows usage; docker system prune removes stopped containers, unused networks and dangling images. Add -a only if you are sure unused images can go.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.