Portainer Docker Setup: Manage All Your Containers From One Clean Dashboard
You're tired of typing docker ps for the hundredth time. You want to see what's running, what's eating memory, and which containers are crashing—without grepping through terminal output. Portainer gives you a web-based UI to manage Docker containers, images, networks, and volumes from a single dashboard. This guide gets you from zero to a fully configured Portainer instance in under 10 minutes.
For a deeper dive into why visual container management beats the CLI for most workflows, check out our companion piece: Portainer Docker Setup: Stop Memorizing CLI Commands and Start Managing Containers Like a Pro.
What You'll Build
By the end of this guide, you'll have:
- Portainer CE running as a Docker container with persistent storage
- HTTPS access via self-signed or custom SSL certificates
- Your local Docker environment connected and visible in the UI
- Multi-environment support configured for staging and production
- Edge agent deployment for remote server management
- Basic security hardening and backup procedures
Prerequisites
Before you start, make sure you have:
- Docker 24.0+ and Docker Compose v2 installed
- sudo access on the host machine
- At least 1GB RAM available for Portainer
- Ports
9443(HTTPS UI) and8000(Edge tunnel) accessible - A modern web browser for accessing the dashboard
- SELinux disabled (or plan to run with
--privilegedif required)
For a comprehensive walkthrough of every Portainer feature and advanced configuration, read our definitive guide: Stop Using the CLI for Everything: The Definitive Portainer Docker Setup Guide.
Step 1: Quick Install with Docker Run
The fastest way to get Portainer running is a single docker run command. This is great for testing before committing to a Compose setup.
Create the Data Volume
docker volume create portainer_data
Run Portainer CE
docker run -d \
-p 8000:8000 \
-p 9443:9443 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:lts
Portainer is now running. The :lts tag gives you the latest long-term support release. Port 9443 serves the HTTPS UI, and port 8000 is for Edge agent tunneling (optional).
Note: Portainer generates a self-signed SSL certificate by default. You'll see a browser warning on first access—this is expected.
Step 2: Production Docker Compose Setup
For anything beyond a quick test, use Docker Compose. It's reproducible, version-controlled, and easier to maintain.
Directory Structure
portainer/
├── docker-compose.yml
└── certs/ # Optional: custom SSL certificates
The docker-compose.yml File
services:
portainer:
container_name: portainer
image: portainer/portainer-ce:lts
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
# Optional: mount custom SSL certs
- ./certs:/certs:ro
ports:
- "9443:9443"
- "8000:8000" # Remove if you don't use Edge Agents
environment:
# Optional: disable internal SSL if using reverse proxy
#- PORTAINER_HTTP_ENABLED=true
#- PORTAINER_HTTPS_ENABLED=false
volumes:
portainer_data:
name: portainer_data
networks:
default:
name: portainer_network
Deploy the Stack
cd portainer
docker compose up -d
Verify it's running:
docker ps
# Should show portainer/portainer-ce:lts with ports 8000 and 9443 mapped
Step 3: First Login and Initial Setup
Open your browser and navigate to:
https://your-server-ip:9443
You'll see a browser warning about the self-signed certificate—accept it and proceed. On first launch, Portainer asks you to:
- Create an admin user — set a strong username and password
- Select your environment — choose "Get Started" to manage the local Docker instance
Once logged in, you'll see the dashboard with all running containers, images, volumes, and networks.
Step 4: Add Multiple Environments
Portainer shines when managing multiple Docker hosts. You can add environments via the Docker socket (local), TCP endpoint, or Edge agent (remote).
Add a Remote Docker Host via TCP
On the remote host, configure Docker to listen on TCP (with TLS recommended):
# Edit /etc/docker/daemon.json
{
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"],
"tls": true,
"tlscacert": "/etc/docker/ca.pem",
"tlscert": "/etc/docker/server-cert.pem",
"tlskey": "/etc/docker/server-key.pem",
"tlsverify": true
}
Then in Portainer UI: Environments → Add Environment → Docker Standalone → API. Enter the remote host IP and port with TLS credentials.
Deploy an Edge Agent (Recommended for Remote Hosts)
Edge agents are lightweight and don't require exposing Docker TCP. In Portainer:
- Go to Environments → Add Environment → Edge Agent
- Name your environment and copy the generated Edge agent command
On the remote host, run:
docker run -d \
-p 9001:9001 \
--name portainer_edge_agent \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/volumes:/var/lib/docker/volumes \
-e EDGE=1 \
-e EDGE_ID=your-edge-id \
-e EDGE_KEY=your-edge-key \
-e EDGE_INSECURE_POLL=1 \
portainer/agent:lts
The agent connects back to your Portainer server over the tunnel (port 8000). No inbound firewall rules needed on the remote host.
Step 5: Configure HTTPS with Custom Certificates
For production, replace the self-signed certificate with a proper one from Let's Encrypt or your CA.
Option A: Mount Certificates Directly
Place your certificates in the certs/ directory:
# Using Let's Encrypt
cp /etc/letsencrypt/live/portainer.yourdomain.com/fullchain.pem certs/cert.pem
cp /etc/letsencrypt/live/portainer.yourdomain.com/privkey.pem certs/key.pem
Then update your Compose file to mount the certs volume (already included in our example above). Portainer automatically detects /certs/cert.pem and /certs/key.pem.
Option B: Reverse Proxy (Recommended)
Put Portainer behind Nginx, Traefik, or Caddy. Update Compose to disable internal HTTPS:
environment:
- PORTAINER_HTTP_ENABLED=true
- PORTAINER_HTTPS_ENABLED=false
ports:
- "9000:9000" # HTTP only, proxy handles TLS
Then configure your reverse proxy to forward to http://portainer:9000.
Step 6: Security Hardening Checklist
Before calling this production-ready, run through this checklist:
Change Default Admin Credentials
Use a strong, unique password for the admin account. Enable two-factor authentication if available in your Portainer edition.
Restrict Access by IP
If Portainer is exposed to the internet, restrict access to known IPs at the firewall level:
# UFW example
ufw allow from 203.0.113.0/24 to any port 9443 proto tcp
ufw deny 9443
Enable Audit Logging
Portainer CE logs authentication events. Monitor these for suspicious activity:
docker logs portainer | grep -i "authentication\|login\|failed"
Backup Portainer Data
The Portainer database lives in the portainer_data volume. Back it up regularly:
#!/bin/bash
# backup-portainer.sh
BACKUP_DIR=/backups
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
docker run --rm \
-v portainer_data:/data \
-v $BACKUP_DIR:/backup \
alpine \
tar czf /backup/portainer-$TIMESTAMP.tar.gz -C /data .
# Keep only last 14 days
find $BACKUP_DIR -name 'portainer-*.tar.gz' -mtime +14 -delete
Add to crontab:
0 3 * * * /path/to/backup-portainer.sh
Tips and Troubleshooting
Portainer won't start: "bind: address already in use"
Check what's using port 9443:
sudo lsof -i :9443
# or
ss -tlnp | grep 9443
Either stop the conflicting service or change the host port in docker-compose.yml.
Cannot connect to Docker socket
If you see permission errors, ensure the Docker socket is readable:
ls -la /var/run/docker.sock
# Should show srwxrwxrwx or similar
# If not, add your user to the docker group:
sudo usermod -aG docker $USER
Edge agent won't connect
Verify port 8000 is open on the Portainer server and the Edge key is correct. Check agent logs:
docker logs portainer_edge_agent
Container stats not showing
Portainer needs access to container metrics. Ensure your Docker daemon has metrics enabled:
# Check if metrics are available
curl --unix-socket /var/run/docker.sock http://localhost/containers/json
Updating Portainer
To update to the latest LTS release:
docker pull portainer/portainer-ce:lts
docker compose up -d
Reset admin password
If you forget the admin password, reset it via the container:
docker stop portainer
portainer_data=$(docker volume inspect portainer_data --format '{{ .Mountpoint }}')
# Remove the authentication database
sudo rm $portainer_data/portainer.db
docker start portainer
Warning: This resets all Portainer configuration. Use as a last resort.
Next Steps
You now have Portainer running and managing your Docker environment. From here, you can:
- Deploy application stacks using Docker Compose templates
- Set up container registries for private image hosting
- Configure role-based access control (RBAC) for team members
- Monitor resource usage and set up alerts
- Automate deployments with Portainer's API and webhooks
For a comprehensive walkthrough of API automation, Edge deployments, security hardening, and container logging at scale, read our advanced guide: Portainer Docker Setup: API Automation, Edge Deployments, Security Hardening, and Container Logging at Scale.
And if you're just getting started and want the full picture of why Portainer beats the CLI, our definitive overview covers it: Stop Using the CLI for Everything: The Definitive Portainer Docker Setup Guide.
Already comfortable with the basics and want pro tips? See: Portainer Docker Setup: Stop Memorizing CLI Commands and Start Managing Containers Like a Pro.
Need Help With Production Container Management?
Setting up Portainer is straightforward. Running it at scale—with multiple environments, team RBAC, automated deployments, and proper monitoring—is where it gets interesting. If your team needs help architecting a production container management strategy, configuring Edge agents across datacenters, or integrating Portainer into your CI/CD pipeline, get in touch with our team at Sysbrix. We've managed container fleets for startups and enterprises alike, and we can get yours running right.