Self Hosting 9 min read

Portainer Guide: Self-Hosted Docker Management Dashboard

Suresh S Suresh S
Portainer Guide: Self-Hosted Docker Management Dashboard

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.yml file and deploy it directly from the browser, with the same result as running docker 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-data volume: Persists Portainer’s own database — user accounts, environment connections, and settings — separately from anything it’s managing.
  • /var/run/docker.sock mount: 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

  1. Navigate to https://<YOUR_SERVER_IP>:9443 in 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.
  2. 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.
  3. Select Get Started, which automatically detects and connects to the local Docker environment via the socket you mounted.
  4. 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.
SectionWhat It Shows
ContainersEvery container’s status, resource usage, and quick actions (start, stop, restart, remove, view logs)
ImagesAll pulled images, with the ability to pull new ones or remove unused ones to free disk space
VolumesEvery Docker volume, including which containers are currently using each one
NetworksDocker networks and which containers are attached to them
StacksCompose-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.

  1. Go to Stacks > Add Stack.
  2. Give the stack a name (e.g., jellyfin).
  3. Paste in the contents of a docker-compose.yml file directly, or use the Repository option to deploy straight from a Git repo containing one.
  4. Click Deploy the stack. Portainer runs the equivalent of docker compose up -d behind the scenes and the new containers appear in your Containers list moments later.
  5. 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:

  1. In Nginx Proxy Manager, add a new Proxy Host.
  2. Set the domain (e.g., portainer.yourdomain.com), forward hostname to your server’s internal IP, and forward port 9443 with the scheme set to HTTPS, since Portainer serves its own TLS certificate internally.
  3. Enable Force SSL and request a Let’s Encrypt certificate for the public-facing side of the proxy.
  4. 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.

  1. 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.
  2. In your primary Portainer dashboard, go to Environments > Add Environment and select Docker Standalone (Agent).
  3. Enter the remote host’s address and the agent’s port, then connect.
  4. 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 / SymptomPrimary CauseTroubleshooting / Diagnostic Action
Setup page says “instance timed out”Admin account not created within the initial time windowRestart the container to reset the setup window, then complete account creation immediately.
Environment shows as unreachableDocker socket not mounted, or agent unreachable on a remote hostVerify the socket mount in docker-compose.yml, or check that the Portainer Agent container is running on the remote host.
Stack fails to deployInvalid compose syntax or a port conflict with an existing containerCheck 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 visitUsing Portainer’s self-signed cert without a reverse proxyPut Portainer behind a reverse proxy with a real Let’s Encrypt certificate, as described in step 6.
High memory usage on the hostA managed container is misbehaving, not Portainer itselfUse the Containers stats view to identify which specific container is responsible before restarting anything.

10. Portainer vs. Alternatives

Feature / MetricPortainer CEDockgeYacht
Hosting ModelSelf-hostedSelf-hostedSelf-hosted
Multi-Host ManagementYes, via AgentNo, single-host focusedLimited
Kubernetes SupportYesNoNo
Stack/Compose EditingFull UI editorFull UI editor, compose-focusedBasic
Role-Based Access ControlYesNoLimited
CostFree (Community Edition)FreeFree

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.

Suresh S

Written by Suresh S

Systems Engineer & Tech Educator with 10+ years of experience in Linux Administration, Cloud Computing, and Cybersecurity. Founder of FreeTechLearner, dedicated to creating practical tutorials that help students and professionals build real-world skills.

Share this post:

Discussion

Loading comments...