Portainer Docker Setup: Stop Managing Containers from the Terminal
You can only type docker ps and docker logs so many times before you lose your mind. This Portainer Docker setup guide gets you a proper web UI for managing containers, stacks, and volumes—deployed in under 5 minutes.
What Is Portainer?
Portainer is a lightweight management UI for Docker, Kubernetes, and Nomad. It wraps the Docker API in a clean web interface so you can start, stop, inspect, and deploy containers without touching the command line.
What you get:
- Container management—start, stop, restart, inspect logs, exec into shells
- Stack deployment—deploy and update Docker Compose stacks from the UI
- Volume and network management—no more orphaned volumes eating disk space
- Multi-environment support—manage multiple Docker hosts from one dashboard
- Role-based access control (BE)—give team members limited access
- Registry integration—pull images from Docker Hub, GHCR, or private registries
It's the tool you install once and wonder how you lived without. For more context, check our related guides on visual container management for developers, stopping the endless docker ps cycle, and a developer's guide to Portainer.
Prerequisites
Before starting this Portainer Docker setup, you need:
Required
- Docker Engine 20.10+ installed and running
- Docker Compose v2+ (for stack deployments)
- A Linux server, VM, or desktop with sudo access
- 1GB RAM minimum (Portainer itself is light; your containers are the heavy part)
Recommended
- 2GB+ RAM if you're running other services on the same host
- A domain name and SSL certificate for HTTPS access
- Basic familiarity with Docker concepts (images, containers, volumes, networks)
Quick Docker Install (if needed)
# Ubuntu/Debian
sudo apt update
sudo apt install -y docker.io docker-compose-v2
sudo usermod -aG docker $USER
newgrp docker
# Verify
docker --version
docker compose version
Step 1: Deploy Portainer Server
Portainer runs as a single container. You can deploy it with docker run or Docker Compose. The Compose approach is cleaner for long-term management.
Option A: Docker Run (Quick)
# Create a volume for persistent data
docker volume create portainer_data
# Run Portainer
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
Option B: Docker Compose (Recommended)
Create a dedicated directory and compose file:
mkdir ~/portainer && cd ~/portainer
nano docker-compose.yml
Paste this:
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"
volumes:
portainer_data:
name: portainer_data
networks:
default:
name: portainer_network
Deploy it:
docker compose up -d
Verify it's running:
docker ps
# Expected output:
# CONTAINER ID IMAGE COMMAND STATUS PORTS
# xxxxxxxx portainer/portainer-ce:lts "/portainer" Up 10 seconds 0.0.0.0:8000->8000/tcp, 0.0.0.0:9443->9443/tcp
Step 2: First Login and Initial Setup
Open your browser to https://your-server-ip:9443.
Note: Portainer uses a self-signed certificate by default. Your browser will warn you. Accept the risk and proceed, or configure your own SSL certificate later.
Initial Admin Account
- Create the first admin user (username, password)
- Select Docker Standalone as the environment type
- Portainer auto-detects the local Docker socket
You're now looking at your Docker host in a web UI. Every container, image, volume, and network is visible.
Enable HTTP Port (Optional)
If you need HTTP port 9000 for legacy reasons or reverse proxy setups, add it to your compose file:
ports:
- "9443:9443"
- "9000:9000" # HTTP fallback
- "8000:8000" # Edge agent tunnel
Step 3: Manage Containers
The Containers page is where you'll spend most of your time. Here's what you can do:
- Start/Stop/Restart/Kill—one click, no CLI
- View logs—real-time streaming with search
- Exec console—open a shell inside any running container
- Inspect—see full JSON config, env vars, mounts, network settings
- Duplicate/Edit—clone a container and tweak its settings
Quick Actions from the UI
Click any container row to expand actions. The console feature is especially useful—no more docker exec -it container_name /bin/sh memorization.
Container Stats
Portainer shows live CPU, memory, and network usage per container. Click the stats icon on any running container to see graphs. This beats running docker stats in a terminal window.
Step 4: Deploy Stacks with Docker Compose
Stacks are Portainer's name for Docker Compose deployments. This is where Portainer shines for production.
Create a New Stack
- Go to Stacks → Add Stack
- Name it (e.g.,
web-apps) - Paste your
docker-compose.ymlcontent or pull from Git - Click Deploy the Stack
Example: Deploy a Web Stack
Paste this into the stack editor:
services:
nginx:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- nginx-html:/usr/share/nginx/html
restart: unless-stopped
redis:
image: redis:alpine
restart: unless-stopped
volumes:
nginx-html:
Portainer pulls the images, creates the volumes, and starts the services. You can update the stack later by editing the compose file and clicking Update the Stack.
Environment Variables in Stacks
Portainer supports .env files and inline environment variables. Use the Environment Variables section below the compose editor to inject secrets without hardcoding them.
Step 5: Secure Portainer for Production
Running Portainer on port 9443 with a self-signed cert is fine for local testing. For production, you need a reverse proxy and proper SSL.
Nginx Reverse Proxy with SSL
Create /etc/nginx/sites-available/portainer:
server {
listen 80;
server_name docker.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name docker.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location / {
proxy_pass https://localhost:9443;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_ssl_verify off; # Portainer uses self-signed cert internally
proxy_read_timeout 86400;
}
}
Enable and get SSL:
sudo ln -s /etc/nginx/sites-available/portainer /etc/nginx/sites-enabled/
sudo nginx -t
sudo certbot --nginx -d docker.yourdomain.com
sudo systemctl reload nginx
Firewall Rules
# Only expose HTTPS to the world
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP (Certbot)
sudo ufw allow 443/tcp # HTTPS
sudo ufw deny 9443/tcp # Block direct Portainer access
sudo ufw enable
Step 6: Add Remote Environments (Optional)
Portainer can manage multiple Docker hosts. Install the Portainer Agent on remote machines and connect them to your main server.
Deploy 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
Add Environment in Portainer UI
- Go to Environments → Add Environment
- Select Docker Standalone → Agent
- Enter the remote host IP and port 9001
- Save and connect
You now manage multiple Docker hosts from one dashboard. No SSH hopping required.
Tips and Troubleshooting
"Cannot connect to the Docker daemon"
Portainer can't reach the Docker socket. Check permissions:
ls -la /var/run/docker.sock
# Should show: srwxr-xr-x 1 root docker ...
# If not, restart Docker:
sudo systemctl restart docker
Portainer won't start after reboot
Make sure the restart policy is set:
docker update --restart=always portainer
# Or in your compose file:
# restart: always
Self-signed certificate warning
This is normal for fresh installs. Either:
- Accept the browser warning for internal use
- Configure your own SSL certificate in Portainer settings
- Use a reverse proxy with Let's Encrypt (recommended)
Reset admin password
# Stop Portainer
docker stop portainer
# Reset password
docker run --rm -v portainer_data:/data portainer/portainer-ce:lts \
--admin-reset-password
# Restart
docker start portainer
Updating Portainer
cd ~/portainer
docker compose down
docker compose pull
docker compose up -d
Backup Portainer data
# Backup the data volume
docker run --rm -v portainer_data:/data -v $(pwd):/backup alpine \
tar czf /backup/portainer-backup-$(date +%Y%m%d).tar.gz -C /data .
Stack deployment fails with "network not found"
Make sure your compose file defines networks explicitly, or use the default bridge. Portainer's stack parser is stricter than docker compose CLI in some cases.
What's Next?
You now have a visual control panel for your Docker infrastructure. Here's what to explore:
- Template deployments—one-click installs for popular apps (WordPress, MySQL, Redis)
- Registry management—connect private registries and pull custom images
- User management (BE)—create teams with limited access to specific environments
- Webhooks—trigger stack redeployments from CI/CD pipelines
- Edge agents—manage IoT and edge devices remotely
Portainer CE is free and open-source. If you need LDAP, RBAC, or audit logs, consider Portainer Business Edition.
Need Help With Production Docker Management?
This Portainer Docker setup guide gets you running, but production environments need more: multi-host orchestration, CI/CD integration, monitoring, backup strategies, and security hardening.
If you're managing Docker infrastructure for your organization and want it done right, get in touch with our team. We specialize in containerized deployments that scale.