Docker lets you run websites, databases, bots and panels in isolated containers, each with its own dependencies and without cluttering the system.
Install it
The official script installs Docker and the Compose plugin on Ubuntu and Debian:
curl -fsSL https://get.docker.com | sh
Check it works:
docker run --rm hello-world
docker compose version
A Compose example
Create a folder with a docker-compose.yml, for example a simple website:
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html:ro
restart: unless-stopped
docker compose up -d # start in the background
docker compose logs -f # watch the logs
docker compose down # stop it
restart: unless-stopped brings it back after a VPS reboot.
Careful: Docker bypasses ufw
Ports you publish with ports: (or -p) are opened to the internet even if ufw says they are closed, because Docker writes its own firewall rules. It is the cause of many accidentally exposed databases.
If a service is only used by other containers or the server itself, publish it locally only:
ports:
- "127.0.0.1:3306:3306"
And containers in the same docker-compose.yml need nothing published to reach each other: they see one another by service name.
Cleaning up
Old images pile up and fill the disk. Every so often:
docker system prune
It removes stopped containers, unused networks and untagged images. It asks for confirmation first.