How to install Portainer and manage Docker containers from the web

Practical guide to install Portainer on Docker, set up HTTPS, and manage containers, volumes, and networks from the web UI without relying on the CLI.

Managing dozens of Docker containers from the command line gets friction-heavy fast: you forget the exact container name, you have to remember the right docker run flags, and auditing volumes or networks requires compound commands. Portainer solves this by offering a web interface that covers 90% of day-to-day operations — start, stop, logs, exec, creating docker-compose stacks, and managing named volumes and networks.

This tutorial is for anyone already running Docker on a Linux server (Ubuntu, Debian, or similar) who wants to add a visual management layer without reinstalling anything. We will install the Community Edition (CE), protect the interface with the self-signed HTTPS certificate that Portainer generates itself, create the admin user, and cover the most common operations. Estimated time: 15 to 25 minutes, depending on Docker familiarity.

The installation described here assumes a single Docker host — the most common scenario. If you operate multiple Docker servers and want a central panel, we mention at the end how to add remote agents later.

Prerequisites

Before you start

You need a Linux server with Docker Engine 20.10 or higher already installed and running, sudo access, and TCP port 9443 free. If port 9443 is taken, adjust the mapping in the install step. Confirm Docker with docker --version before continuing.

Parameters used throughout the tutorial:

Portainer HTTPS port 9443
Agent port (optional) 9001
Data volume portainer_data
Official image portainer/portainer-ce:latest

If you are putting this on a production server exposed to the internet, also consider having a domain pointing to the server IP — it makes it easier later to swap the self-signed certificate for a valid Let’s Encrypt one through a reverse proxy.

Installing Portainer Server

The recommended official install uses a dedicated Docker container with a named volume to persist configuration and data. There is no need to clone a repository or compile anything — the official image covers all cases.

01

Create the Docker volume that will hold Portainer’s data (internal database, settings, users, templates):

docker volume create portainer_data

The named volume ensures that any upgrade or recreation of the Portainer container preserves users, endpoints, and configuration. Without it, a docker rm wipes everything.

02

Start the Portainer Server container with automatic restart:

docker run -d \
  -p 9443:9443 \
  -p 8000:8000 \
  --name portainer \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  portainer/portainer-ce:latest

Four important things in this command:

  • 9443 is the default HTTPS port (self-signed certificate generated on first boot)
  • 8000 is the Edge Agents tunnel port — only needed if you plan to use remote agents behind NAT later, you can omit it for now
  • The /var/run/docker.sock socket bind is what gives Portainer full control over the host Docker
  • --restart=always makes the container come back automatically after a server reboot
03

Confirm that the container is up and healthy:

docker ps --filter "name=portainer"

The output should show the container with status Up X seconds and the port 0.0.0.0:9443->9443/tcp exposed. If it doesn’t appear, run docker logs portainer to see the error — usually it is a port conflict or an inaccessible Docker socket.

5-minute window for the first admin

For security reasons, Portainer only accepts the creation of the first admin user within 5 minutes after the container starts. If the window expires, the panel shows a security message and you have to restart the container (docker restart portainer) to open a new window.

First access and admin creation

With the container running, open the browser and go to https://SERVER_IP:9443. The browser will warn about an untrusted certificate — that is expected; Portainer generates a self-signed certificate on first start. Accept the warning and proceed.

04

On the first screen, set the administrator user:

  • Username: admin (or whatever you prefer)
  • Password: minimum 12 characters, with letters, numbers, and symbols
  • Confirmation of the same password

Save the password in a password manager before submitting. Recovery is only possible through the reset procedure with a temporary container (described in the FAQ).

05

On the next screen, choose the environment to manage. Since Portainer was installed on the same host as Docker, click Get Started — that automatically connects to the local socket you mounted in step 2.

The main dashboard appears showing the summary: number of running containers, stopped ones, local images, volumes, networks, and stacks. That is the starting point for all operations.

Day-to-day operations

The left side menu groups all functions. The three areas you will use most are Containers, Volumes, and Networks, all inside the local endpoint.

Managing existing containers

The container list shows name, state, base image, internal IP, and exposed ports. Each container has inline actions: start, stop, restart, kill, remove. Clicking the container name gives you access to:

  • Logs — live log tail with filter and auto-scroll. Equivalent to docker logs -f.
  • Stats — CPU, memory, network, and disk I/O charts refreshing every second.
  • Console — interactive terminal inside the container, equivalent to docker exec -it. Lets you choose the shell (sh, bash) and the user.
  • Inspect — full container JSON, useful for debugging configuration.

Creating containers from the interface

The Add container screen replaces docker run. The fields cover all the main flags:

  • Image: the image to use (can be remote like nginx:latest or local)
  • Always pull the image: equivalent to --pull=always
  • Port mapping: list of host:container mappings
  • Volumes: bind mounts or named volumes
  • Network: which Docker network to connect to
  • Restart policy: no, on-failure, unless-stopped, always
  • Env variables: environment variables as key/value pairs
  • Capabilities, runtime, devices: advanced parameters on separate tabs
Use Stacks for docker-compose

For any application with more than one service (app + database + redis, for example), use the Stacks section instead of creating containers individually. Paste a docker-compose.yml straight into the editor — Portainer deploys it and keeps the services grouped for coordinated updates and removals.

Volumes and networks

The Volumes section lists all named volumes, shows the driver, consumed size, and which containers are using each one. You can create new volumes with specific drivers (local, NFS) and remove orphan volumes with one click — handy shortcut to free up disk space after removing test containers.

The Networks section shows the Docker networks (default bridge, host, none, plus any you create). Creation supports bridge and overlay drivers, with options to set a custom subnet and enable IPv6.

Verifying the installation

To confirm everything is working, run this end-to-end test:

docker run -d --name portainer-test nginx:alpine

Reload the Containers screen in Portainer. The portainer-test container should appear within 2 seconds. Click it, go to Logs, and confirm you see the nginx startup lines. Then use the Remove button in Portainer to delete it — confirm via terminal:

docker ps -a | grep portainer-test

The output should be empty. If the full cycle worked, the installation is validated.

Troubleshooting

Error “Cannot connect to the Docker daemon”

The Docker socket is not mounted correctly inside the Portainer container. Check that the -v /var/run/docker.sock:/var/run/docker.sock flag was used in docker run and that the socket exists on the host with ls -la /var/run/docker.sock. On systems with restrictive SELinux or AppArmor, you may need to add :z at the end of the bind (/var/run/docker.sock:/var/run/docker.sock:z).

Port 9443 already in use

Another service is listening on that port. Identify it with sudo ss -tlnp | grep 9443 and either stop the conflicting service or change Portainer’s port by recreating the container with -p 9444:9443 (or any free port). The internal mapping stays 9443 — only the host side changes.

Browser blocks access due to invalid certificate

Expected behavior on first install because of the self-signed certificate. For real-world use, place Portainer behind a reverse proxy (nginx or Caddy) with a Let’s Encrypt certificate — the proxy handles public TLS and Portainer responds with HTTP internally on the Docker network.

Next steps

With Portainer running, it is worth exploring:

  1. Create a Stack with docker-compose to bring up coordinated multi-container applications
  2. Configure your own Templates — pre-made recipes with variables to speed up repetitive deploys
  3. Add an Agent on a second server to manage multiple hosts from the same panel
  4. Enable private Registries (private Docker Hub, GitHub Container Registry) in the Registries section
  5. Put a reverse proxy with Let’s Encrypt in front to have valid HTTPS on your own domain

If you are running Portainer in production to manage critical workloads, a Hostini VPS on a dedicated plan gives you dedicated CPU and fast snapshots — useful for testing Portainer upgrades or rolling back stacks that fail. See the options at /vps.

Frequently asked questions

Is Portainer CE free for commercial use?

Yes. The Community Edition (CE) is open source under the Zlib license and can be used commercially with no limit on hosts or users. The Business edition adds granular RBAC, corporate OAuth integration, and official support — only worth it for teams with specific compliance requirements.

Can I install Portainer without exposing port 9443 to the internet?

You can, and it is recommended. Keep port 9443 listening only on 127.0.0.1 and access it via SSH tunnel (ssh -L 9443:127.0.0.1:9443 user@server). Alternative: leave the port public but firewall-restricted to your source IP, or place a reverse proxy with extra authentication in front.

What is the difference between Portainer Server and Portainer Agent?

Server is the web interface and the orchestrator — you install one per environment. Agent is a lightweight container that runs on each additional host you want to manage from the same Portainer, communicating over port 9001. For a single Docker host, the Server alone is enough.

What happens if I lose the admin password?

There is an official reset procedure: stop the Portainer container, run portainer/helper-reset-password as a temporary container mounting the same portainer_data volume, copy the password generated in the log, and start Portainer again. The reset preserves all configured endpoints and templates.

Can I migrate existing Docker containers into Portainer?

Yes, automatically. Portainer detects containers, images, volumes, and networks that already exist on the Docker host as soon as it connects to the socket. No data is moved or rewritten — Portainer just reads the state and offers a graphical interface on top of it.

Why doesn't Portainer show real-time CPU and memory stats?

Metrics collection depends on the Docker cgroup driver. If the host uses cgroup v2 (default on recent distros), Portainer 2.19+ works natively. On older cgroup v1, check whether DOCKER_OPTS includes --exec-opt native.cgroupdriver=systemd and restart the Docker daemon.

Topics:
Next steps Ryzen cloud with NVMe storage and always-on DDoS protection.Go live on a Hostini VPS →
Was this tutorial helpful?
Chat on WhatsApp