Portainer Docker Setup: A Developer's Guide to Visual Container Management
You can manage Docker containers from the command line. But should you? Portainer gives you a web-based interface to deploy, monitor, and troubleshoot containers across single or multiple hosts. This guide covers a complete Portainer Docker setup—from installation to production security—with commands you can copy and paste.
If you want to see what the dashboard looks like before diving in, check out Portainer Docker Setup: Manage All Your Containers From One Clean Dashboard for a visual walkthrough.
What You Need Before You Start
Portainer is lightweight, but it assumes your environment meets a few baseline requirements. Get these right first to avoid headaches later.
Required
- Docker Engine installed and running on Linux (not Docker Desktop)
- sudo access on the host machine
- Port 9443 available for the web UI
- Port 8000 available if you plan to use Edge Agents
Assumptions
- Docker is running as root. Rootless Docker works but needs extra configuration.
- SELinux is disabled or configured to allow privileged containers.
- You are accessing Docker via the Unix socket at
/var/run/docker.sock.
Do not install Docker via snap on Ubuntu. It causes volume mount and socket compatibility issues. Use the official Docker installation instructions instead.
Installing Portainer with Docker Run
The fastest path to a running Portainer instance is a single docker run command. Here is the exact sequence.
Step 1: Create the Data Volume
Portainer stores its configuration, user accounts, and environment data in a Docker volume. Create it first:
docker volume create portainer_data
Step 2: Run the Portainer Server Container
Pull and start the Portainer CE LTS image with the correct flags:
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
What each flag does:
-d: Detached mode (runs in the background)-p 8000:8000: Edge Agent tunnel server (optional—remove if you do not need Edge Agents)-p 9443:9443: HTTPS web UI--restart=always: Restarts the container automatically after reboots or crashes-v /var/run/docker.sock:/var/run/docker.sock: Gives Portainer access to the Docker daemon-v portainer_data:/data: Persists Portainer's SQLite database
Portainer generates a self-signed SSL certificate for port 9443 by default. If you need legacy HTTP access on port 9000, add -p 9000:9000 to the command.
Step 3: Verify the Container
docker ps
Expected output:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7963585688a9 portainer/portainer-ce:lts "/portainer" 8 seconds ago Up 8 seconds 0.0.0.0:8000->8000/tcp, [::]:8000->8000/tcp, 0.0.0.0:9443->9443/tcp, [::]:9443->9443/tcp, 9000/tcp portainer
Open https://your-server-ip:9443 in a browser. You will see the initial setup screen where you create the admin user.
For a perspective on why this beats rote CLI memorization, read Portainer Docker Setup: Stop Memorizing CLI Commands and Start Managing Containers Like a Pro.
Installing Portainer with Docker Compose
For teams managing multiple services, Docker Compose is cleaner and easier to version control. Here is a production-ready configuration.
The Compose 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
ports:
- 9443:9443
- 8000:8000 # Remove if you do not intend to use Edge Agents
volumes:
portainer_data:
name: portainer_data
networks:
default:
name: portainer_network
Save this as portainer-compose.yaml and deploy:
docker compose -f portainer-compose.yaml up -d
Benefits of Compose over raw docker run:
- Infrastructure lives in version-controlled YAML
- Easy to add reverse proxies, monitoring, or additional services later
- One command to tear down and rebuild the entire stack
Managing Multiple Hosts with the Portainer Agent
One Portainer Server can manage many Docker hosts. You do not need to install a full Portainer instance on each machine—just the lightweight Agent.
Deploy the Agent on a Remote Host
docker run -d \
-p 9001:9001 \
--name portainer_agent \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/volumes:/var/lib/docker/volumes \
portainer/agent:lts
In the Portainer UI, go to Environments → Add Environment → Docker Standalone and enter the remote host's IP address with port 9001. The Server connects to the Agent over TCP and pulls in all containers, images, and volumes from that host.
This setup scales from one server to ten without SSHing into each box.
Day-to-Day Container Management in Portainer
Once logged in, the dashboard shows every resource across your connected environments. Here is what you can do without opening a terminal.
Start, Stop, Kill, and Restart
Select any container from the list. Action buttons are at the top of the detail page. No more docker stop followed by docker start.
Read Live Logs
Open a container, click Logs, and get a real-time stream with search and download options. This replaces docker logs -f container_name.
Open an Interactive Console
Click Console inside a running container. Portainer opens a shell session in your browser. It is faster than docker exec -it container_name /bin/sh and works from any device with a browser.
Deploy Stacks from Git
Go to Stacks → Add Stack → Repository, paste a Git URL, and Portainer pulls the compose file and deploys it automatically. This is ideal for CI/CD pipelines and infrastructure-as-code workflows.
For the definitive guide on replacing CLI workflows entirely, see Stop Using the CLI for Everything: The Definitive Portainer Docker Setup Guide.
Securing Your Portainer Installation
A web UI that controls Docker is powerful. It is also a target. Lock it down.
Put It Behind a Reverse Proxy
Never expose port 9443 directly to the internet. Use Nginx, Traefik, or Caddy with a valid SSL certificate. Here is a minimal Nginx configuration:
server {
listen 443 ssl http2;
server_name portainer.yourdomain.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
location / {
proxy_pass https://localhost:9443;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Use Authentication and RBAC
Portainer CE supports local users and LDAP integration. Portainer Business Edition adds role-based access control with these built-in roles:
- Read-Only User: View resources, no modifications
- Standard User: Deploy and manage their own stacks and containers
- Operator: Restart, update, and inspect existing resources. Cannot create or delete.
- Environment Administrator: Full access within a specific environment
- Administrator: Global access including user and environment management
Even on CE, create individual user accounts for team members instead of sharing the admin password.
Restrict Network Access
If Portainer sits in a private network, bind it to an internal IP so it is not reachable from public interfaces:
docker run -d \
-p 10.0.0.5:9443:9443 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:lts
Tips, Troubleshooting, and Common Pitfalls
Here are the problems we see most often and how to fix them.
Portainer Does Not Start After Reboot
Confirm the --restart=always flag is set. If the container still fails, check whether Docker itself is enabled:
sudo systemctl status docker
sudo systemctl enable docker
Cannot Reach the Web UI
- Run
docker psto confirm the container is up - Check firewall rules—port 9443 must be open
- Use
https://, nothttp:// - Self-signed certificates trigger browser warnings. Accept the exception or provision a real certificate
Permission Denied on Docker Socket
Verify the socket exists and is accessible:
ls -la /var/run/docker.sock
If SELinux is enforcing, either disable it or add --privileged to the Portainer run command.
Database Corruption After Power Loss
Portainer uses SQLite, which can corrupt on unclean shutdowns. Back up the volume regularly:
docker run --rm -v portainer_data:/data -v $(pwd):/backup alpine \
tar czf /backup/portainer-backup-$(date +%F).tar.gz -C /data .
Agent Connection Fails
- Confirm port 9001 is open on the remote host's firewall
- Verify the Agent container is running with
docker ps - Test connectivity from the Portainer Server:
nc -zv remote-ip 9001
Container Logs Appear Empty
Portainer captures stdout and stderr only. If a container logs to a file inside its filesystem, those logs will not appear in the UI. Redirect logs to the console or mount the log file as a volume.
When to Upgrade to Portainer Business Edition
Portainer CE is sufficient for personal projects and small teams. When you scale, Portainer BE adds features that matter:
- Granular RBAC and team isolation
- GitOps automation for stack deployments
- Registry management for private Docker images
- Multi-environment management with access controls
- Professional support and SLA guarantees
For teams managing production workloads across multiple hosts, the time saved on access control, audit trails, and automated deployments pays for the license.
Conclusion
A proper Portainer Docker setup turns container management from a command-line chore into a visual, team-friendly workflow. You have the install commands, the Docker Compose file, the security hardening steps, and the troubleshooting fixes.
Deploy it on your next server and stop typing docker ps every ten minutes.
Running containers at scale and need help with multi-environment Portainer deployments? Contact our team for enterprise container management consulting and infrastructure setup.