If your home lab has grown past two or three containers, you’ve probably felt the friction of managing everything through docker compose commands and docker logs -f in a terminal — checking which container is using too much memory, restarting a stuck service, or updating an image all mean SSHing in and remembering the right flags. Portainer replaces that with a web dashboard: start, stop, and inspect containers, deploy new stacks, manage volumes and networks, and watch resource usage in real time, all from a browser.
It’s free for personal use (the Community Edition, which is what this guide covers), open-source, and — fittingly — it runs as just another Docker container itself, so it fits directly into a stack you’re already managing.
This guide walks through the full Docker deployment, connecting to your existing containers, deploying stacks through the UI, and securing the dashboard.
1. How Portainer Works
Portainer doesn’t replace the Docker engine — it sits alongside it as a management layer. When you install Portainer, it connects to the Docker socket on the host (or to a remote Docker API endpoint), which gives it visibility into every container, image, volume, and network the engine manages. Any action you take in the Portainer UI — starting a container, pulling an image, editing a stack — is translated into the same Docker API calls the docker CLI would make, so nothing about how Docker itself behaves changes; you’re just interacting with it through a browser instead of a terminal.
Portainer organizes what it manages under “environments” — a single Docker host counts as one environment, but you can also connect Portainer to multiple remote Docker hosts or a Kubernetes cluster from the same dashboard, giving you one pane of glass across an entire home lab instead of one browser tab per machine. Configuration and connection details are stored in Portainer’s own local database, separate from anything Docker itself manages, so uninstalling Portainer never affects the containers it was overseeing.
- Docker Socket Access: Connects to the host’s Docker daemon to read and control every container, image, volume, and network.
- Stack Deployment: Lets you paste or upload a
docker-compose.ymlfile and deploy it directly from the browser, with the same result as runningdocker compose up. - Multi-Environment Management: Manages multiple Docker hosts, Docker Swarm clusters, or Kubernetes clusters from a single dashboard.
- Resource Monitoring: Displays live CPU, memory, and network usage per container without needing separate monitoring tooling for basic checks.
- Role-Based Access: Supports multiple user accounts with different permission levels, useful if more than one person manages the same host.
2. System Prerequisites
Portainer’s own footprint is small — the overhead comes from what it’s managing, not from Portainer itself.
- CPU: Negligible; a single core is more than enough for the dashboard and API.
- RAM: 512 MB is generally sufficient for the Portainer container itself.
- Storage: Under 200 MB for the application and its local database.
- Software: Docker and Docker Compose already installed on the host you want to manage — Portainer needs an existing Docker installation to attach to.
If you haven’t set up Docker yet, our guide on installing Docker on Ubuntu covers the full setup from a clean system.
3. Step-by-Step Docker Installation
Create a dedicated directory for the deployment:
mkdir -p ~/portainer
cd ~/portainer
The Docker Compose File
nano docker-compose.yml
version: "3.8"
services:
portainer:
container_name: portainer
image: portainer/portainer-ce:latest
volumes:
- portainer-data:/data
- /var/run/docker.sock:/var/run/docker.sock
ports:
- 9443:9443
restart: unless-stopped
volumes:
portainer-data:
Explaining the Configuration
portainer-datavolume: Persists Portainer’s own database — user accounts, environment connections, and settings — separately from anything it’s managing./var/run/docker.sockmount: Required so Portainer can talk to the host’s Docker daemon and control containers. This is a broad permission — Portainer effectively has full control over Docker on this host, so treat access to the dashboard with the same care you’d give root access.- Port
9443: The default HTTPS dashboard port, using a self-signed certificate out of the box. You’ll place this behind a reverse proxy with a real certificate in step 6.
Launch the stack:
sudo docker compose up -d
Check the logs to confirm a clean startup:
sudo docker compose logs -f
4. Initial Setup & Connecting to Docker
- Navigate to
https://<YOUR_SERVER_IP>:9443in your browser. Your browser will warn about the self-signed certificate — this is expected until you put a reverse proxy in front of it in step 6. - Create your administrator account with a username and a strong password. This step must be completed within a short window after the container first starts, or the setup endpoint locks and the container needs a restart.
- Select Get Started, which automatically detects and connects to the local Docker environment via the socket you mounted.
- You’ll land on the environment dashboard, showing every container, image, volume, and network already running on the host — including ones you deployed before Portainer even existed.
| Section | What It Shows |
|---|---|
| Containers | Every container’s status, resource usage, and quick actions (start, stop, restart, remove, view logs) |
| Images | All pulled images, with the ability to pull new ones or remove unused ones to free disk space |
| Volumes | Every Docker volume, including which containers are currently using each one |
| Networks | Docker networks and which containers are attached to them |
| Stacks | Compose-based deployments, editable and redeployable directly from the UI |
5. Deploying a Stack from the UI
One of Portainer’s most useful features is deploying a full docker-compose.yml stack without touching a terminal — handy for managing other self-hosted services from the same dashboard you’re already using to watch resource usage.
- Go to Stacks > Add Stack.
- Give the stack a name (e.g.,
jellyfin). - Paste in the contents of a
docker-compose.ymlfile directly, or use the Repository option to deploy straight from a Git repo containing one. - Click Deploy the stack. Portainer runs the equivalent of
docker compose up -dbehind the scenes and the new containers appear in your Containers list moments later. - To update a running stack later — say, to change an environment variable or bump an image tag — edit the stack’s compose file in the UI and click Update the stack, which redeploys with the new configuration.
6. Securing the Dashboard with a Reverse Proxy
Portainer effectively holds the keys to your entire Docker host, so the dashboard deserves the same level of protection as your most sensitive service — arguably more. If you’re already running Nginx Proxy Manager for other self-hosted services, our Nginx Proxy Manager security guide covers hardening it properly — the same proxy host pattern applies here:
- In Nginx Proxy Manager, add a new Proxy Host.
- Set the domain (e.g.,
portainer.yourdomain.com), forward hostname to your server’s internal IP, and forward port9443with the scheme set to HTTPS, since Portainer serves its own TLS certificate internally. - Enable Force SSL and request a Let’s Encrypt certificate for the public-facing side of the proxy.
- Strongly consider restricting access to the dashboard’s domain to your VPN or local network only, rather than exposing it to the open internet at all — there’s rarely a good reason to manage Docker from outside your home network, and the risk of an exposed management plane is high.
Our Linux security commands guide and Fail2Ban guide are useful next steps for locking down the host this container runs on.
7. Managing Multiple Hosts
If your home lab spans more than one machine, Portainer can manage all of them from a single dashboard rather than juggling a separate login per host.
- On any additional Docker host, deploy the Portainer Agent — a lightweight companion container that exposes that host’s Docker API to your main Portainer instance.
- In your primary Portainer dashboard, go to Environments > Add Environment and select Docker Standalone (Agent).
- Enter the remote host’s address and the agent’s port, then connect.
- Switch between environments from the dropdown at the top of the dashboard — each one shows its own containers, images, and stacks, all managed from the same login.
8. Backing Up Your Portainer Data
Portainer’s own configuration — user accounts, environment connections, and stack definitions — lives inside the portainer-data volume. It doesn’t back up the containers or volumes it manages; those need their own backup routines, like the ones covered in the other guides in this series.
#!/bin/bash
BACKUP_DIR="/home/suresh/portainer/backups"
TIMESTAMP=$(date +%F)
mkdir -p "$BACKUP_DIR"
# Archive the Portainer data volume's contents
docker run --rm -v portainer-data:/data -v "$BACKUP_DIR":/backup alpine \
tar -czf "/backup/portainer_$TIMESTAMP.tar.gz" -C /data .
# Retain only the last 14 days of backups
find "$BACKUP_DIR" -type f -name "portainer_*.tar.gz" -mtime +14 -delete
Schedule it with cron for daily execution, and sync the backup directory offsite using the same rsync pattern covered in our self-hosted backup strategies guide.
9. Troubleshooting & Maintenance
| Issue / Symptom | Primary Cause | Troubleshooting / Diagnostic Action |
|---|---|---|
| Setup page says “instance timed out” | Admin account not created within the initial time window | Restart the container to reset the setup window, then complete account creation immediately. |
| Environment shows as unreachable | Docker socket not mounted, or agent unreachable on a remote host | Verify the socket mount in docker-compose.yml, or check that the Portainer Agent container is running on the remote host. |
| Stack fails to deploy | Invalid compose syntax or a port conflict with an existing container | Check the deployment logs shown in the UI immediately after a failed deploy — they usually point to the exact line or conflict. |
| Dashboard certificate warning every visit | Using Portainer’s self-signed cert without a reverse proxy | Put Portainer behind a reverse proxy with a real Let’s Encrypt certificate, as described in step 6. |
| High memory usage on the host | A managed container is misbehaving, not Portainer itself | Use the Containers stats view to identify which specific container is responsible before restarting anything. |
10. Portainer vs. Alternatives
| Feature / Metric | Portainer CE | Dockge | Yacht |
|---|---|---|---|
| Hosting Model | Self-hosted | Self-hosted | Self-hosted |
| Multi-Host Management | Yes, via Agent | No, single-host focused | Limited |
| Kubernetes Support | Yes | No | No |
| Stack/Compose Editing | Full UI editor | Full UI editor, compose-focused | Basic |
| Role-Based Access Control | Yes | No | Limited |
| Cost | Free (Community Edition) | Free | Free |
11. Conclusion
Portainer turns Docker management from a terminal-only skill into something anyone comfortable clicking around a dashboard can handle — checking on containers, deploying new stacks, and freeing up disk space without memorizing CLI flags. Paired with a properly restricted reverse proxy and a regular backup of its own configuration, it becomes the control panel that ties the rest of a self-hosted stack together.
Once your management dashboard is live, make sure the rest of your self-hosted stack is watching over it too. Check out our guides on setting up Uptime Kuma monitoring and the complete home server security checklist to keep tabs on what’s running alongside Portainer.
Discussion
Loading comments...