Skip to Content

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.

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:9000 if 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:

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.

LiteLLM Setup Proxy: The Complete Developer Guide to a Unified LLM Gateway
Build a production-ready unified LLM gateway that routes requests to 100+ providers with a single OpenAI-compatible API.