Portainer Docker Setup: The Developer's Guide to Visual Container Management
Deploy Portainer in minutes and manage all your Docker containers, stacks, and environments from a single web dashboard.
What This Guide Covers
If you're still SSHing into servers to run docker ps and docker logs, you're working harder than you need to. Portainer is a lightweight web UI that wraps Docker's CLI in a clean, visual interface. You can start containers, inspect logs, manage volumes, deploy stacks from Git, and monitor resource usage—all from your browser.
This Portainer Docker setup guide walks you through installing Portainer CE on a single Docker host, connecting remote environments, deploying a stack, and securing the instance. By the end, you'll have a central dashboard for every container you run. For a quick overview of why visual container management beats the terminal, see Portainer Docker Setup: Stop Typing docker ps and Start Managing Containers Like a Human.
Prerequisites
Before you start, make sure you have:
- Docker Engine installed and running (v20.10+ recommended)
- sudo or root access on the host machine
- A modern web browser
- Optional: additional Docker hosts you want to manage remotely
Portainer does not support Docker installed via Snap on Ubuntu—use the official Docker repository instead. For a broader look at Portainer's features, check out Portainer Docker Setup: A Developer's Guide to Visual Container Management.
Step 1: Install Portainer Server
Portainer consists of two parts: the Server (the web UI) and the Agent (runs on remote hosts). Start with the server.
Option A: Docker Run (Quickest)
Create a volume for Portainer's database, then start the container:
docker volume create portainer_data
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
Port mappings explained:
9443– HTTPS web UI (default)8000– TCP tunnel server for Edge Agents (optional)9000– legacy HTTP port (add-p 9000:9000if you need it)
Option B: Docker Compose (Recommended)
For reproducible deployments, use a compose file:
version: '3.8'
services:
portainer:
image: portainer/portainer-ce:lts
container_name: portainer
restart: always
ports:
- "8000:8000"
- "9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
volumes:
portainer_data:
name: portainer_data
networks:
default:
name: portainer_network
Deploy it:
docker compose up -d
Verify the container is running:
docker ps --filter name=portainer
Step 2: Complete Initial Setup
Open your browser and navigate to:
https://your-server-ip:9443
Portainer generates a self-signed certificate by default, so your browser will warn you. Accept the risk and continue.
On first launch, you'll create an admin user. Set a strong password—this account has full control over your Docker environment. After that, select Docker Standalone as your environment type and click Connect.
Step 3: Connect Remote Environments
The real power of Portainer is managing multiple hosts from one dashboard. You have two options: the traditional Agent or the Edge Agent.
Option A: Edge Agent (Recommended for Remote Hosts)
The Edge Agent is ideal when the remote host is behind NAT or a firewall. The agent polls Portainer instead of the other way around, so no inbound ports need to be opened on the remote machine.
In the Portainer UI, go to Environments → Add environment → Docker Standalone → Edge Agent Standard. Enter a name and your Portainer server's public URL. Portainer generates a one-liner deployment command. Run it on the remote host:
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 Edge Agent will appear in your Portainer dashboard within seconds. No firewall rules needed.
Option B: Traditional Agent (For Local Network Hosts)
If the remote host is on the same network and port 9001 is accessible, use the traditional agent:
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
Then in Portainer, add the environment with the host's IP and port 9001.
For a deeper dive into managing all your containers from one place, see Portainer Docker Setup: Manage All Your Containers From One Clean Dashboard.
Step 4: Deploy a Stack from Portainer
Stacks are Portainer's way of managing Docker Compose deployments. You can create them via the web editor, upload a file, or pull from Git.
Deploy from the Web Editor
Go to Stacks → Add stack, name it, and paste your compose file:
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
redis:
image: redis:alpine
restart: always
Click Deploy the stack. Portainer will create the containers, networks, and volumes automatically.
Deploy from a Git Repository
For GitOps workflows, connect Portainer to a Git repo. Go to Stacks → Add stack → Git Repository, enter your repo URL, select the branch, and specify the compose file path. Enable GitOps updates to auto-redeploy when the repo changes—either by polling or via a webhook.
Environment Variables in Stacks
You can define variables directly in the UI or load them from a .env file. Reference them in your compose file:
services:
app:
image: myapp:latest
environment:
DATABASE_URL: ${DATABASE_URL}
API_KEY: ${API_KEY}
This keeps secrets out of your compose file and makes the same file reusable across environments.
Step 5: Manage Containers, Images, and Volumes
Once Portainer is connected to an environment, you get a full management interface.
Containers
The Containers view shows running and stopped containers. You can start, stop, restart, pause, remove, or inspect any container with a click. Logs and console access are built in—no more docker exec -it for quick debugging.
Images
View pulled images, check for updates, and pull new versions. Portainer shows image size and layer details, and lets you remove unused images to reclaim disk space.
Volumes
Inspect volume usage, see which containers mount each volume, and clean up orphaned volumes. This is especially useful on long-running hosts where volumes accumulate over time.
Networks
Create and manage Docker networks. Portainer shows which containers are attached to each network, making it easy to debug connectivity issues.
Step 6: Secure Your Portainer Instance
Portainer controls your entire Docker environment. Lock it down.
Use a Reverse Proxy with HTTPS
Instead of exposing port 9443 directly, put Portainer behind a reverse proxy. Here's a minimal Nginx config:
server {
listen 443 ssl;
server_name portainer.yourdomain.com;
ssl_certificate /etc/nginx/ssl/cert.crt;
ssl_certificate_key /etc/nginx/ssl/key.key;
location / {
proxy_pass https://localhost:9443;
proxy_http_version 1.1;
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;
}
}
Or use Caddy for automatic HTTPS:
portainer.yourdomain.com {
reverse_proxy https://localhost:9443 {
transport http {
tls_insecure_skip_verify
}
}
}
Enable Authentication and RBAC
Portainer CE supports local users and OAuth/LDAP integration. Create separate user accounts instead of sharing the admin login. In Portainer BE, you get role-based access control (RBAC) to restrict which environments and stacks each user can see.
Set an Agent Secret
If you're using the traditional Agent, set a shared secret so only your Portainer Server can connect:
# On the Portainer Server
docker run -d ... -e AGENT_SECRET=your-secret ...
# On the Agent host
docker run -d ... -e AGENT_SECRET=your-secret ...
Tips, Troubleshooting, and Gotchas
1. Can't Access the Web UI
If you can't reach https://your-ip:9443, check that the container is running and the ports are mapped correctly. Also verify your firewall allows traffic on 9443:
sudo ufw allow 9443/tcp
sudo ufw reload
2. Docker Snap Installation Breaks Portainer
Docker installed via Snap uses a different socket path and confinement model. Portainer cannot access /var/run/docker.sock in this setup. Uninstall Snap Docker and install from the official repo:
sudo snap remove docker
curl -fsSL https://get.docker.com | sh
3. Edge Agent Won't Connect
If the Edge Agent stays offline, check three things: the EDGE_KEY is correct, the Portainer server URL is reachable from the agent host, and the tunnel port (8000) is open on the server. For self-signed certificates, make sure EDGE_INSECURE_POLL=1 is set.
4. Stack Deployment Fails with "Service Not Found"
This usually means the compose file references a network or volume that doesn't exist. Portainer creates networks automatically, but named external volumes must exist beforehand. Create them manually or let the compose file define them inline.
5. Orphaned Stacks After Deleting an Environment
If you delete an environment, its stacks become orphaned. Recover them by going to Stacks → Show all orphaned stacks and re-associating them to a new environment.
6. High Memory Usage on the Portainer Container
Portainer itself is lightweight, but managing hundreds of containers across many environments increases memory use. If you see high usage, check the Events and Logs views for runaway polling or large image lists. Restarting the container usually clears transient spikes.
Next Steps
You now have a central dashboard for managing Docker containers across multiple hosts. From here, you can:
- Set up GitOps deployments for continuous delivery
- Configure registry authentication for private image pulls
- Enable container resource limits and monitoring
- Deploy Portainer BE for RBAC, audit logs, and support
For more Portainer content, explore our related guides:
- Portainer Docker Setup: Stop Typing
docker psand Start Managing Containers Like a Human - Portainer Docker Setup: A Developer's Guide to Visual Container Management
- Portainer Docker Setup: Manage All Your Containers From One Clean Dashboard
Need Help Scaling This?
Running Portainer for a single host is easy. Running it at scale—with dozens of environments, GitOps pipelines, RBAC, and high availability—is where things get serious. If your team needs a production-grade container management platform without the operational headaches, reach out to us. We design, deploy, and operate Docker infrastructure for engineering teams that ship fast.