Why Do You Need Portainer?
In self-hosting and VPS operations, Docker containerization has become the standard. But command-line Docker operations are not beginner-friendly, and management complexity rises sharply as the number of containers grows. Portainer provides an intuitive web UI that lets you:
- Visually monitor all containers: status, resource consumption, and network connections
- One-click application deployment: via templates and Stacks (Compose files)
- Image and volume management: browse, pull, and remove images; manage persistent storage
- Multi-host management: manage multiple servers from a single Portainer instance
- Role-based access control: fine-grained permissions for team collaboration
Prerequisites
Assuming you have a VPS running Ubuntu 22.04/24.04 or Debian 12, with at least 1GB RAM.
# Update the system
sudo apt update && sudo apt upgrade -y
# Install Docker (if not already installed)
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
# Verify Docker is running properly
docker version
docker info
Method 1: Deploy Portainer via Docker Container (Recommended)
The simplest way to run Portainer Server via Docker:
# Create a Portainer data volume for persistence
docker volume create portainer_data
# Start Portainer Server
docker run -d \
--name portainer \
--restart always \
-p 9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
Parameter explanation:
-p 9443:9443: Maps the container’s 9443 port to the host (HTTPS)-v /var/run/docker.sock: Mounts the Docker socket, allowing Portainer to control Docker-v portainer_data:/data: Persists Portainer’s configuration and data
After starting, visit https://your-ip:9443, set the admin password, and you’re in.
⚠️ Security Note: For initial setup, using HTTP port 8000 is simpler:
docker run -d \ --name portainer \ --restart always \ -p 8000:8000 \ -p 9443:9443 \ -p 80:80 \ -v /var/run/docker.sock:/var/run/docker.sock \ -v portainer_data:/data \ portainer/portainer-ce:latest
Method 2: Deploy Using Docker Compose
For more structured management, Docker Compose is recommended:
# docker-compose.yml
version: '3.8'
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: always
ports:
- "9443:9443"
- "8000:8000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
networks:
- portainer_net
volumes:
portainer_data:
networks:
portainer_net:
driver: bridge
docker compose up -d
Method 3: Traefik Reverse Proxy Integration
If you’re already using Traefik as a reverse proxy, you can auto-configure Portainer via labels:
version: '3.8'
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.portainer.rule=Host(`portainer.yourdomain.com`)"
- "traefik.http.routers.portainer.entrypoints=websecure"
- "traefik.http.routers.portainer.tls.certresolver=letsencrypt"
- "traefik.http.services.portainer.loadbalancer.server.port=9443"
networks:
- proxy
volumes:
portainer_data:
networks:
proxy:
external: true
First Use: Portainer Interface Overview
After logging in, you’ll see these core functional areas:
1. Environment Management
Portainer uses the concept of “environments” to manage different Docker hosts. On first login, it guides you to choose:
- Local environment: Docker on the current server
- Remote environment: Docker engines on other servers
2. Container Management
Click “Containers” to see all running containers, each showing:
- CPU/Memory usage
- Running status (Running/Stopped/Restarting)
- Network port mappings
- Uptime
Common operations:
- Start/Stop/Restart: One-click container lifecycle control
- Logs: View real-time log output
- Exec: Enter the container to execute commands
- Inspect: View detailed container configuration
- Clone/Update: Quickly rebuild based on existing configuration
3. Image Management
Manage all downloaded Docker images:
- Pull new images
- Remove unused images to free space
- View image details and layer information
Periodic cleanup command (also available via Portainer UI):
docker system prune -a --volumes
4. Stack Deployment (Compose Management)
Portainer’s most powerful feature is Stacks—it allows you to edit and deploy Docker Compose files through the web UI.
Example: Deploying Nextcloud:
version: '3.8'
services:
nextcloud:
image: nextcloud:latest
container_name: nextcloud
restart: always
ports:
- "8080:80"
volumes:
- nextcloud_data:/var/www/html
- nextcloud_config:/var/www/html/config
environment:
- MYSQL_HOST=db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nc_user
- MYSQL_PASSWORD=your_secure_password
networks:
- nextcloud_net
db:
image: mariadb:10.11
container_name: nextcloud_db
restart: always
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
volumes:
- db_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nc_user
- MYSQL_PASSWORD=your_secure_password
networks:
- nextcloud_net
volumes:
nextcloud_data:
nextcloud_config:
db_data:
networks:
nextcloud_net:
driver: bridge
In the Portainer UI:
- Left menu → Stacks → Add stack
- Select “Build” mode (from local docker-compose.yml file)
- Paste the configuration above
- Click “Deploy the stack”
Advanced Features
Multi-Host Management
Portainer supports unified management of Docker engines across multiple servers:
- Start the Portainer Agent on managed servers:
docker volume create portainer_agent_data
docker run -d \
--name portainer-agent \
--restart always \
-p 9001:9001 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_agent_data:/data \
portainer/agent:latest
- In the main Portainer:
- Settings → Environments → Add environment environment
- Select “Agent” type
- Enter the remote server’s IP and port 9001
- Enter the Agent key (viewable in Settings → Endpoint synchronization)
Security Hardening
1. Enable HTTPS
Using Let’s Encrypt certificates:
# Install certbot
sudo apt install certbot -y
# Obtain certificate
sudo certbot certonly --standalone -d portainer.yourdomain.com
# Modify docker-compose.yml to mount certificates
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
- /etc/letsencrypt/live/portainer.yourdomain.com/fullchain.pem:/cert/fullchain.pem
- /etc/letsencrypt/live/portainer.yourdomain.com/privkey.pem:/cert/privkey.pem
2. Configure Reverse Proxy Authentication
Add Basic Auth in front of Nginx:
server {
listen 443 ssl;
server_name portainer.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/portainer.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/portainer.yourdomain.com/privkey.pem;
location / {
auth_basic "Portainer Admin";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass https://localhost:9443;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Generate htpasswd file:
sudo apt install apache2-utils -y
sudo htpasswd -c /etc/nginx/.htpasswd admin
3. Restrict Network Access
Allow Portainer access only from specific IPs:
# Using UFW firewall
sudo ufw allow from your-admin-IP to any port 9443
sudo ufw deny 9443
Backup and Restore
Portainer’s configuration is stored in the portainer_data volume, making backups straightforward:
# Backup Portainer data
docker run --rm \
-v portainer_data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/portainer_backup_$(date +%Y%m%d).tar.gz -C /data .
# Restore
docker run --rm \
-v portainer_data:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/portainer_backup_YYYYMMDD.tar.gz -C /data
Monitoring and Alerting Integration
Portainer itself doesn’t provide alerting, but it integrates well with external tools:
Auto-Updates with Watchtower
version: '3.8'
services:
watchtower:
image: containrrr/watchtower
container_name: watchtower
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_POLL_INTERVAL=3600 # Check every hour
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_NOTIFICATIONS=shoutrrr
- WATCHTOWER_NOTIFICATION_SHOUTRRR_URLS=discord://your-webhook-url
- WATCHTOWER_NOTIFICATION_SHOUTRRR_TITLE=Portainer Update Alert
Prometheus Integration
Portainer provides API endpoints that can be integrated into a Prometheus monitoring stack.
Troubleshooting
Q1: Portainer cannot connect to Docker socket
Cause: Docker socket permission issue or incorrect container mounting.
Solution:
# Check if Docker socket exists
ls -la /var/run/docker.sock
# Verify Portainer container has correct mount
docker inspect portainer | grep docker.sock
Q2: Container starts and immediately exits
Cause: Image pull failure or port conflict.
Solution:
# Check container logs
docker logs portainer
# Check port conflicts
ss -tlnp | grep 9443
Q3: How to migrate Portainer to another server?
Steps:
- On the old server, backup the
portainer_datavolume - Install Docker and Portainer on the new server
- Restore the backup data to the new server’s
portainer_datavolume - Start Portainer and re-import your environment configurations
Q4: What’s the difference between Portainer CE and EE?
| Feature | CE (Community) | EE (Enterprise) |
|---|---|---|
| Cost | Free | Paid |
| Container Management | ✅ | ✅ |
| Stack Deployment | ✅ | ✅ |
| Multi-Host Management | ✅ | ✅ |
| RBAC Permissions | Basic | Advanced |
| Kubernetes Management | ❌ | ✅ |
| Audit Logs | ❌ | ✅ |
| Support | Community | Official |
For individuals and small teams, the CE version is more than sufficient.
Best Practices Summary
- Always use volumes: Never store important data inside containers; use named volumes or bind mounts
- Set restart policies: Configure
restart: alwaysorrestart: unless-stoppedfor all critical services - Regular backups: At minimum, back up Portainer data and container volumes weekly
- Use network isolation: Create separate Docker networks for different services
- Limit exposed ports: Only expose ports when necessary; use a reverse proxy to统一管理 entries
- Keep updated: Regularly update Portainer and all container images
- Enable log rotation: Prevent log files from filling up disk space
Alternatives Comparison
| Tool | Pros | Cons |
|---|---|---|
| Portainer | Feature-rich, beautiful UI, active community | Requires extra resources |
| Docker Compose CLI | Zero overhead, lightweight | Only suitable for few containers |
| Rancher | K8s support, enterprise-grade | Resource-heavy, complex |
| Coolify | Heroku-like experience, free | Newer project, smaller ecosystem |
| Landoop UI | Minimalist, container-focused | Limited features |
Conclusion
Portainer is a powerful tool for VPS operators, simplifying complex Docker operations into visual clicks. Whether you’re a newcomer to containers or a seasoned operator managing dozens of services, Portainer significantly boosts productivity.
Combined with reverse proxy, auto-updates, and regular backups, you can build a reliable production-grade container management platform.
This guide applies to Ubuntu 22.04/24.04, Debian 12, and Docker 24+.
