Table of Contents
Docker has become the de facto standard for packaging and deploying applications. Whether you're running a simple Python script or orchestrating a full microservices stack, containers give you consistency from your laptop to production. In this guide, I'll walk you through a complete Vultr Docker setup — from provisioning a Vultr Ubuntu VPS to running production-ready containers.
Why Docker on Vultr?
Vultr's infrastructure pairs exceptionally well with Docker for several reasons:
- High-performance SSD storage on all plans — critical for container image layers and volume I/O
- Global presence with 32 locations — deploy containers close to your users for lower latency
- Flexible instance sizing — start at $2.50/month for testing, scale up to dedicated CPU instances for production workloads
- Full root access — no artificial restrictions on Docker daemon or container networking
The combination means you get enterprise-grade infrastructure at startup-friendly prices, with none of the "Docker-in-a-VM" limitations you'll hit on some other VPS providers.
Prerequisites
For this guide, I'm assuming you've already provisioned a Vultr instance. Here's what I'll be using:
- Vultr instance: 4 vCPU, 8GB RAM, 160GB SSD (~$40/month)
- OS: Ubuntu 24.04 LTS
- User: Non-root sudo user (I'll call him
deploy)
If you haven't set up your Vultr account yet, use this affiliate link — it supports the guides I write here at no extra cost to you.
Step-by-Step Docker Installation
1. Update Your System
First things first — bring your Ubuntu installation up to date:
sudo apt update && sudo apt upgrade -y
This ensures you have the latest kernel and system libraries before installing Docker. It's a step many tutorials skip, and then they wonder why they hit weird container networking issues.
2. Install Dependencies
Docker requires a few packages that aren't included in a minimal Ubuntu install:
sudo apt install -y ca-certificates curl gnupg lsb-release
3. Add Docker's Official GPG Key and Repository
Vultr's Ubuntu images are clean, so we can follow Docker's official installation method without fighting edge cases:
sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
4. Install Docker Engine
sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
This installs not just the Docker daemon, but also BuildKit (for faster image builds) and Docker Compose v2 (the plugin-based version that ships with docker compose instead of the standalone docker-compose).
5. Verify the Installation
sudo docker run --rm hello-world
If you see the "Hello from Docker!" message, your installation is working correctly. If you get a permission error, you likely need to add your user to the docker group:
sudo usermod -aG docker deploy # Log out and back in for the group change to take effect
Post-Installation Configuration
Configure Docker Daemon
For production workloads, you'll want to tune the Docker daemon. Create or edit /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2",
"live-restore": true,
"default-address-pools": [
{ "base": "172.17.0.0/16", "size": 24 }
]
}
Key settings explained:
- log-driver + log-opts — Limits container logs to 10MB per file with 3 rotating files. Prevents your disk from filling up with runaway logs.
- storage-driver: overlay2 — The recommended storage driver for Ubuntu. Fast and well-maintained.
- live-restore — Containers stay running during Docker daemon restarts. Critical for production uptime.
- default-address-pools — Avoids IP conflicts with other Docker networks on your VPS.
Apply the changes:
sudo systemctl restart docker sudo systemctl enable docker
Using Docker Compose
Docker Compose is how you define multi-container applications. Let's set up a practical example — a Nginx reverse proxy forwarding to two Python Flask services.
Create the Project Structure
mkdir -p ~/projects/flask-app && cd ~/projects/flask-app mkdir -p app nginx
Write the Flask Application
Create app/app.py:
from flask import Flask
import os
app = Flask(__name__)
@app.route("/")
def hello():
return f"Hello from Flask! Container ID: {os.environ.get('HOSTNAME', 'unknown')}"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Create app/requirements.txt:
flask==3.0.0
Create app/Dockerfile:
FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "app.py"]
Write the Docker Compose File
Create docker-compose.yml in the project root:
services:
web:
build: ./app
restart: always
expose:
- "5000"
networks:
- appnet
nginx:
image: nginx:alpine
restart: always
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- web
networks:
- appnet
networks:
appnet:
driver: bridge
Create nginx/nginx.conf:
events {
worker_connections 1024;
}
http {
upstream flask_backend {
server web:5000;
}
server {
listen 80;
server_name _;
location / {
proxy_pass http://flask_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
Launch the Stack
docker compose up -d --build
Verify everything is running:
docker compose ps curl http://localhost
You should see "Hello from Flask!" with a container ID. That's your Docker Compose stack live and routing through Nginx.
Production Deployment Example
The example above is great for learning, but a real production setup needs a few additions. Here's what I'd layer on top for a typical web application:
Automatic Restart Policies
Add restart policies to docker-compose.yml:
services:
web:
# ... existing config ...
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
These resource limits prevent a runaway container from consuming all available memory and destabilizing your Vultr VPS.
Monitoring with Docker Stats
Get real-time resource usage across all containers:
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.Status}}"
For long-term monitoring, consider integrating Prometheus and Grafana via Docker Compose — you can run the full observability stack on the same Vultr instance without additional cost.
Backup Strategy
For containerized applications on Vultr, I recommend three layers of backup:
- Volume backups — Use Vultr's automated block storage snapshots for persistent data volumes
- Application backups — Schedule database dumps within your containers
- Configuration-as-code — Keep your
docker-compose.ymland application configs in Git
Security Best Practices
Running Docker on a public VPS exposes you to different threat models than running locally. Here's what I always implement:
- Never run containers as root inside the container — Add a
USERdirective to your Dockerfiles - Bind Docker socket carefully — Never expose
/var/run/docker.sockto other containers without thinking hard about the implications - Keep images updated — Run
docker compose pullregularly to patch vulnerabilities - Use .dockerignore — Prevent sensitive files from being copied into image layers
- Configure a UFW firewall — Only expose ports that need to be public (80, 443). Docker bypasses UFW by default on Ubuntu — here's how to fix that
# Recommended UFW setup for Docker hosts sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow ssh sudo ufw allow http sudo ufw allow https # Edit /etc/default/ufw and set DEFAULT_FORWARD_POLICY="ACCEPT" # Add to /etc/ufw/sysctl.conf: net/ipv4/ip_forward=1 sudo ufw enable
Ready to Deploy Your First Container?
Get started with Vultr's high-performance SSD VPS from $2.50/month. New accounts get $100 in credits.
Deploy Your Vultr Server →Conclusion
A proper Vultr Docker setup takes about 20 minutes and gives you a production-ready container platform. The key takeaways:
- Use Ubuntu 24.04 LTS with Docker's official APT repository for the smoothest install experience
- Configure
/etc/docker/daemon.jsonwith log rotation andlive-restorebefore deploying anything - Start with Docker Compose for multi-container apps — it makes your entire stack reproducible and version-controlled
- Always set resource limits on containers in production to prevent noisy-neighbor issues
- Layer in monitoring and backup strategies from day one, not as an afterthought
With Docker running on Vultr's infrastructure, you have a platform that's as capable as anything you'd get from AWS or GCP — at a fraction of the cost, and with full control over the host. For teams building modern web applications, APIs, or data pipelines, this is one of the best cost-to-performance ratios available in 2026.
If you found this guide useful, check out my companion piece on Vultr scaling strategies for growing applications — it covers how to take your Docker setup from a single instance to a distributed, load-balanced architecture.