Introduction

Docker simplifies application deployment but can waste resources if not optimized. This guide covers best practices for running Docker on a Hostxpeed VPS: container resource limits, storage optimization, network choices, and security hardening.

When to Use Docker on VPS

Docker is ideal for microservices, multi-language environments, or isolating apps on a single VPS. Avoid Docker if you have a single monolithic app that runs fine natively, or if you need maximum performance (native runs 5-10% faster). On a VPS, Docker adds overhead but provides reproducibility and easy updates.

Choosing Storage Driver

Default overlay2 is best for performance. Check: docker info | grep "Storage Driver". For NVMe, overlay2 works great. For high I/O workloads (databases), consider using host volumes (bind mounts) instead of overlay layers. Avoid aufs (deprecated), devicemapper (slow). For temporary data, use tmpfs mounts. Also set up periodic docker system prune to clean unused images, containers, volumes.

Setting Resource Limits per Container

Without limits, a container can consume all VPS resources. In docker run: --cpus="1.5" (limit to 1.5 cores), --memory="1g", --memory-swap="2g" (total memory+swap). For docker-compose: deploy: resources: limits: cpus: 1, memory: 1G. Use --oom-kill-disable to avoid system OOM killer (not recommended). Also set --pids-limit=100 to limit number of processes. Monitor with docker stats.

Networking Options for Performance

Default bridge network (docker0) has NAT overhead. For better performance, use host network mode (--net=host) for latency-sensitive apps (avoids port mapping). For isolation, use macvlan (container gets own IP on host network). For multi-container apps, use user-defined bridge network (supports DNS resolution). Avoid default bridge for production. For inter-container communication, place them on same custom network.

Persistent Data: Volumes vs Bind Mounts

Use named volumes for database data (managed by Docker, better performance on some filesystems). Use bind mounts for config files and code (editable from host). For MySQL, place data on host directory (bind mount) with noexec,nosuid options. Ensure you back up volume data separately. Avoid storing database data inside container writable layer (slow, lost on container remove).

Log Management to Prevent Disk Filling

By default, Docker logs all container stdout/stderr without rotation. Set log driver: --log-opt max-size=10m --log-opt max-file=3. In docker-compose: logging: driver: "json-file", options: max-size: "10m", max-file: "3". For central logging, use Fluentd or Loki. Monitor disk usage: du -sh /var/lib/docker/containers/. Clean old logs: docker container prune.

Security Hardening for Docker on VPS

Run containers as non-root user (--user 1000:1000). Use read-only root filesystem (--read-only) and mount writable dirs as tmpfs for temporary files. Drop unnecessary capabilities: --cap-drop=ALL --cap-add=NET_ADMIN (only required). Use seccomp profiles. Don't expose Docker socket to containers (unless necessary). Use AppArmor profiles. Scan images for vulnerabilities: docker scan (Snyk). Update base images weekly.

Docker Compose for Multi-Container Apps

Define services in docker-compose.yml. Set resource limits per service. Use depends_on for startup order (but not readiness). Use environment variables for config. Example: version: 3.8, services: web: image: nginx:alpine, ports: "80:80", deploy: resources: limits: cpus: 0.5, memory: 256M. For production, consider Docker Swarm or Kubernetes for orchestration.

Building Efficient Docker Images

Minimize image size: use alpine or slim variants. Chain RUN commands to reduce layers. Use multi-stage builds to exclude build dependencies. Example: FROM golang:alpine AS builder, then copy binary to alpine final image. This reduces final image from 500MB to 20MB. Also use .dockerignore. For Node.js, install only production dependencies (npm ci --production). Keep base images updated.

Monitoring Docker Containers

Use docker stats for real-time. Use cAdvisor (runs as container) to export metrics to Prometheus. Also netdata auto-detects Docker and shows per-container metrics. Set up alerts for containers restarting too often (unhealthy). Monitor disk usage of /var/lib/docker. Use third-party tools like Portainer for GUI management.

Backup and Restore Docker Data

Backup volumes: docker run --rm -v volume_name:/data -v $(pwd):/backup alpine tar czf /backup/volume_backup.tar.gz /data. Restore similarly. Also backup docker-compose.yml and .env files. For databases, use native dump inside container: docker exec -t db_container pg_dumpall > backup.sql. Avoid backing up entire /var/lib/docker (too large, not portable).

Performance Tuning Docker

Use --ulimit to adjust open files, processes. For high I/O, use --storage-opt overlay2.override_kernel_check=true. Increase kernel parameters: vm.max_map_count=262144 for Elasticsearch. Place Docker root directory on fastest storage (NVMe). Use CPU sets (--cpuset-cpus) for dedicated cores. For real-time apps, use --cpu-rt-runtime (requires kernel config).

Common Pitfalls and Solutions

Container eating all RAM -> set memory limit. Orphaned volumes -> docker volume prune. Port conflicts -> change host port mapping. Slow disk I/O on database -> use bind mount with direct I/O option (--mount type=bind,src=...,dst=...,volume-opt=o=direct). Container timezone wrong -> mount /etc/localtime. Host network mode breaks multiple containers using same port -> different approach. Networking between containers on different compose projects -> create external network.

Orchestration: When to Move Beyond Docker Compose

If you have 1-5 containers, Compose sufficient. For more, or need scaling, use Docker Swarm (built-in) or Kubernetes (complex). Swarm mode on single VPS? Not beneficial. For high availability across multiple VPS, consider Kubernetes (k3s) or Nomad. Hostxpeed offers managed Kubernetes add-on (beta).

Conclusion: Docker + VPS Works Well

Docker on VPS provides flexibility at moderate overhead (5-15% depending on workload). Apply resource limits to prevent starvation, use efficient base images, and monitor logs. Hostxpeed NVMe storage and dedicated CPUs make Docker containers perform well. Start with docker-compose, monitor with netdata, and prune regularly. For most web apps, Docker simplifies deployment updates when used responsibly.