Docker is essential for running containerized applications. This guide covers multiple methods for running Docker on Proxmox VE.
Installation Methods
Alpine Docker LXC Lightweight Container
Minimal resource usage
Fast deployment
Best for: Simple Docker workloads
Docker VM Full Virtual Machine
Complete isolation
Multiple OS options
Best for: Production environments
Alpine Docker Container (LXC)
Quick Installation
Run the Alpine Docker Script
bash -c "$( wget -qLO - https://github.com/community-scripts/ProxmoxVE/raw/main/ct/alpine-docker.sh)"
Container Configuration
Default settings:
CPU: 1 core
RAM: 1024 MB
Disk: 2 GB
OS: Alpine 3.23
Unprivileged: Yes
Verify Installation
pct enter < CTI D >
docker --version
docker ps
Why Alpine?
Lightweight Base container ~50 MB vs 300+ MB for Ubuntu
Secure Minimal attack surface with fewer packages
Fast Quick startup and low resource usage
Docker VM (Full Installation)
For production workloads, a full VM provides better isolation and flexibility.
Quick Installation
Run the Docker VM Script
bash -c "$( wget -qO - https://github.com/community-scripts/ProxmoxVE/raw/main/vm/docker-vm.sh)"
Choose Operating System
Select from:
Debian 13 (Trixie) - Latest
Debian 12 (Bookworm) - Stable (recommended)
Ubuntu 24.04 LTS - Long-term support
Ubuntu 22.04 LTS - Older LTS
Cloud-Init Configuration
Enable Cloud-Init for:
Automatic user setup
SSH key injection
Network configuration
First-boot customization
Wait for Installation
The script will:
Download OS image
Pre-install Docker
Configure networking
Start the VM
Default VM Configuration
Setting Default Value VM ID Next available Machine Type Q35 (Modern) Disk Size 10 GB Hostname docker CPU Model Host CPU Cores 2 RAM 4096 MB Network vmbr0
The Docker VM script pre-installs Docker during image creation, so it’s ready immediately after first boot.
Docker Configuration
Optimized Daemon Settings
The scripts automatically configure Docker with optimized settings:
{
"storage-driver" : "overlay2" ,
"log-driver" : "json-file" ,
"log-opts" : {
"max-size" : "10m" ,
"max-file" : "3"
}
}
Configuration location: /etc/docker/daemon.json
overlay2 is the recommended storage driver for performance and stability.
Verify Docker Installation
# Enter the container
pct enter < CTI D >
# Check Docker version
docker --version
# Test with hello-world
docker run hello-world
# SSH into VM or use console
ssh root@ < vm-i p >
# Check Docker version
docker --version
# Verify service is running
systemctl status docker
# Test installation
docker run hello-world
Running Docker Containers
Basic Container Management
Run a Container
docker run -d -p 80:80 --name webserver nginx:latest
Docker Compose
Docker Compose is pre-installed in VMs. For Alpine containers:
# Install Docker Compose (Alpine)
apk add docker-compose
Example docker-compose.yml:
version : '3.8'
services :
web :
image : nginx:alpine
ports :
- "80:80"
restart : unless-stopped
db :
image : postgres:15-alpine
environment :
POSTGRES_PASSWORD : changeme
volumes :
- postgres_data:/var/lib/postgresql/data
restart : unless-stopped
volumes :
postgres_data :
Run with:
Storage Configuration
Persistent Volumes
For data persistence, use Docker volumes:
# Create a volume
docker volume create mydata
# Use in container
docker run -v mydata:/data nginx:alpine
# List volumes
docker volume ls
Bind Mounts
Mount host directories:
# Create directory
mkdir -p /opt/appdata
# Mount in container
docker run -v /opt/appdata:/data nginx:alpine
For LXC containers, ensure the directory permissions match between host and container.
Increasing Disk Space
# Resize container disk
pct resize < CTI D > rootfs +10G
# Resize VM disk
qm resize < VMI D > scsi0 +10G
# Inside VM, resize partition
growpart /dev/sda 1
resize2fs /dev/sda1
Networking
Container Networking
Bridge Network Default Docker network docker network create mynetwork
Host Network Use host’s network stack docker run --network host nginx
Port Mapping
# Map container port to host
docker run -p 8080:80 nginx
# Map to specific interface
docker run -p 192.168.1.100:8080:80 nginx
# Map multiple ports
docker run -p 80:80 -p 443:443 nginx
Macvlan Network
For containers to appear as separate devices on network:
# Create macvlan network
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 macvlan_net
# Run container on macvlan
docker run --network macvlan_net \
--ip=192.168.1.100 nginx
Portainer
Web-based Docker management:
docker run -d \
-p 9000:9000 \
--name portainer \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
Access at: http://<ip>:9000
Dockge
Docker Compose management UI:
# Or use the community script
bash -c "$( wget -qLO - https://github.com/community-scripts/ProxmoxVE/raw/main/tools/addon/dockge.sh)"
Yacht
Container management for beginners:
docker run -d \
-p 8001:8000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v yacht:/config \
selfhostedpro/yacht
CPU Limits
Limit CPU usage:
# Limit to 50% of one core
docker run --cpus= "0.5" nginx
# Limit to specific cores
docker run --cpuset-cpus= "0,1" nginx
Memory Limits
# Set memory limit
docker run -m 512m nginx
# Set memory + swap limit
docker run -m 512m --memory-swap 1g nginx
Storage Optimization
Clean Everything
docker system prune -a --volumes
Pruning removes all unused containers, images, and volumes. Ensure you have backups.
Security Best Practices
Use Unprivileged Containers # Run as non-root user
docker run --user 1000:1000 nginx
Read-Only Filesystem # Mount root as read-only
docker run --read-only nginx
Limit Capabilities # Drop all capabilities
docker run --cap-drop=ALL nginx
Use Secrets # Use Docker secrets
echo "mypassword" | docker secret create db_pass -
Rootless Docker
For enhanced security, run Docker without root:
# Install rootless Docker
curl -fsSL https://get.docker.com/rootless | sh
# Enable at boot
systemctl --user enable docker
Backup and Restore
Backup Containers
Commit Container
Backup Volumes
# Save container as image
docker commit mycontainer mybackup:latest
# Export image
docker save -o backup.tar mybackup:latest
# Backup volume to tar
docker run --rm \
-v myvolume:/data \
-v $( pwd ) :/backup \
alpine tar czf /backup/volume-backup.tar.gz /data
Restore from Backup
# Load image
docker load -i backup.tar
# Restore volume
docker run --rm \
-v myvolume:/data \
-v $( pwd ) :/backup \
alpine tar xzf /backup/volume-backup.tar.gz -C /
Proxmox-Level Backup
Always backup the entire container/VM for complete restoration: vzdump < CTI D > --mode snapshot --compress zstd
Troubleshooting
Docker daemon not starting
Check service status: systemctl status docker
journalctl -u docker -n 50
Restart Docker:
Add user to docker group: Or use sudo:
Check Docker disk usage: Clean up: Resize container/VM disk
Network connectivity issues
Restart networking: Check iptables:
Advanced Topics
Docker Swarm
For container orchestration:
# Initialize swarm
docker swarm init
# Deploy stack
docker stack deploy -c docker-compose.yml mystack
Custom Docker Registry
Run a private registry:
docker run -d -p 5000:5000 \
--restart unless-stopped \
--name registry \
-v registry-data:/var/lib/registry \
registry:2
Docker BuildKit
Enable BuildKit for faster builds:
export DOCKER_BUILDKIT = 1
docker build -t myapp .
Next Steps
Popular Apps Explore pre-configured applications
Networking Advanced network configuration
Security Harden your Docker setup