Skip to content
VeloxMedia
VPS guide

Install Docker and Docker Compose on an Ubuntu VPS

Every VeloxMedia plan is a full VMware virtual machine, so Docker runs exactly as it would on physical hardware. This guide installs it the supported way and adds the configuration most tutorials leave out.

Intermediate · About 3 min read · Updated 27 October 2026

Why not the distribution package?

Ubuntu's own docker.io package works, but it lags behind upstream and does not include the current Compose plugin. Docker's repository gives you current Engine, Buildx and Compose releases with security fixes delivered through normal apt upgrades.

1. Remove conflicting packages

for p in docker.io docker-doc docker-compose podman-docker containerd runc; do
  sudo apt remove -y $p 2>/dev/null
done

2. Add Docker's repository

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

On Debian, replace ubuntu with debian in both URLs.

3. Install Engine and Compose

sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo docker run --rm hello-world
docker compose version

4. Decide about the docker group

Adding your user to the docker group lets you run commands without sudo:

sudo usermod -aG docker $USER

Be aware that membership is effectively root access, because anyone in the group can start a container that mounts the host filesystem. On a single-admin server that is usually acceptable; on shared servers, keep using sudo.

5. Rotate container logs

By default Docker keeps container logs forever, and a chatty container can fill the disk. Cap them globally:

sudo tee /etc/docker/daemon.json >/dev/null <<'EOF'
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" }
}
EOF
sudo systemctl restart docker

The limits apply to containers created after the restart.

6. A Compose file that survives reboots

Create ~/app/compose.yaml:

services:
  web:
    image: nginx:stable
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
  db:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets: [db_password]
    volumes:
      - dbdata:/var/lib/postgresql/data
secrets:
  db_password:
    file: ./db_password.txt
volumes:
  dbdata:

Start it with docker compose up -d. Note the port binding: 127.0.0.1:8080 keeps the container private to the host. Put nginx with Let's Encrypt in front for public HTTPS. Binding to localhost matters because Docker's published ports bypass UFW rules, as explained in our UFW guide.

7. Housekeeping

docker compose pull && docker compose up -d   # update images
docker system df                              # see what uses space
docker image prune -a --filter "until=168h"   # remove unused images older than a week

Schedule the prune with a weekly cron job on build-heavy servers.

Sizing

A couple of small containers run happily on Small. Five to ten services with a database fit Medium, and CI runners building images benefit from the extra cores of Pro.

Common questions

Can I run Docker on a VeloxMedia VPS?

Yes. Every plan is a full VMware virtual machine with root access, so Docker Engine, Compose and container orchestration tools install and run normally.

Should I use docker.io or docker-ce on Ubuntu?

Use docker-ce from Docker's official repository. It provides current Engine and Compose releases and security updates through apt, while docker.io from the Ubuntu archive tends to lag behind.

Why is my container port reachable even though UFW blocks it?

Docker adds iptables rules for published ports that are evaluated before UFW. Publish ports on 127.0.0.1 and expose them through a reverse proxy instead.

How do I stop Docker logs filling the disk?

Set a global log size limit in /etc/docker/daemon.json, for example max-size 10m and max-file 3 for the json-file driver, restart Docker, and recreate the containers.

Deploy your first server in under a minute

Pick a region, choose a size and connect over SSH. No setup fees, cancel anytime.