Skip to content

Portainer

Portainer CE, the community edition, shows what Docker is running and lets you act on it from the browser: containers, logs, volumes, networks and images, with restart, exec, stop and image pulls a click away. It reaches the Docker daemon through a socket proxy that decides which API calls pass; Portainer itself never holds the socket. Two services: Portainer and the socket proxy. For stacks deployed from Git, Dockhand is the other management interface here.

Last run on a host 8 Nov 2026

Pinned at 2.45.3 (released 21 Oct 2026) · the newest upstream release

In the upstream images: 0 CRITICAL · 6 HIGH with a published fix — per image

To try it: Docker, nothing else. See Try it locally.

To deploy it behind the proxy: Traefik running and a domain.

On your own machine, with no proxy, domain or certificate. From core/portainer/:

Terminal window
cp .env.local.example .env.local
docker compose -f docker-compose.local.yml --env-file .env.local up -d
docker compose -f docker-compose.local.yml --env-file .env.local logs app | grep setup_token

Open http://localhost:9000 within five minutes, paste the token into Setup token and create the administrator. Stop it again with the same command and down.

From core/portainer/:

  1. Copy the environment file and set APP_TRAEFIK_HOST and TZ:

    Terminal window
    cp .env.example .env

    There is no secret to generate: the first administrator is created in the interface.

  2. List portainer-edge in EDGE_NETWORKS in core/traefik/.env, then render and restart Traefik — see edge networks.

  3. Start it and read the setup token, which Portainer prints once:

    Terminal window
    docker compose up -d
    docker compose logs portainer-app | grep setup_token
  4. Within five minutes of the start, open https://<APP_TRAEFIK_HOST>, paste the token into Setup token, and create the administrator with a strong password.

  5. Turn on two-factor authentication in the user settings.

The setup token is what keeps whoever reaches the page during those five minutes from claiming the instance. Portainer asks for the same token when it restores from a backup. Past the five minutes the setup locks until the container restarts.

Terminal window
docker compose ps # two services, healthy
docker compose logs socket-proxy # the API calls the proxy handles

In the interface, list the containers, open one’s logs and pull an image.

The proxy’s environment in docker-compose.yml is the permission set:

Variables Grant
CONTAINERS, SERVICES, NETWORKS, VOLUMES, IMAGES, SYSTEM read access
EXEC, POST, DELETE changes
ALLOW_START, ALLOW_STOP, ALLOW_RESTARTS container lifecycle

As shipped, that is full access for a trusted administrator. Anything that can change containers is equivalent to root on the host. For a read-only view, set POST, DELETE and EXEC to "0".

The route ships access-vpn, limit-strict and headers-standard, and names tls-strict as its TLS option. If the interface comes up blank or half-rendered on a cold cache, the proxy answered 429 to its first load: move to limit-standard, which keeps the headers and widens the burst to 500.

The Portainer Agent, core/portainer-agent/, puts another host into the same interface. Edge agents connect back to the central Portainer on TCP 8000, which this stack does not publish: it carries no TLS and only EDGE_KEY as authentication. Publish it on a VPN address only, never 0.0.0.0. The steps are in the agent’s README. Dockhand with Hawser covers several hosts over HTTPS through Traefik, without an extra port.

Database an embedded key-value store in volumes/data — no database server, no dump hook
State volumes/data — users, environments, stacks, registries, access policies
Quiescing stop the container or snapshot the filesystem; the store is written continuously

For borgmatic, back up volumes/data with the container stopped. Portainer’s own backup function, in the interface, writes one encrypted archive; write it to a path the file backup covers.

What a loss costs is the environment definitions and access policies, not the containers — everything Portainer manages keeps running while it is down.

Portainer migrates its database at start, one way.

  1. Read the release notes.

  2. Back up volumes/data — the complete Portainer state.

  3. Raise APP_TAG in .env, then:

    Terminal window
    docker compose pull && docker compose up -d
    docker compose logs portainer-app --tail 100
  4. Log in, and check that the environments still connect and the users are there.

To roll back, restore volumes/data and set the previous APP_TAG.

The setup page refuses to create the administrator. The five-minute window has passed. docker compose restart portainer-app, read the new token, and open the page again.

The interface loads blank or half-rendered. limit-strict answered 429 to the first load — see Who can reach it.

An action fails with a permission error from Docker. The socket proxy does not grant that API call. Check its variables, then docker compose up -d.

An edge agent loops on a failed handshake. The environment was not saved in the interface before EDGE_ID and EDGE_KEY were copied.