Portainer - Container Manager
Portainer is a web interface for managing Docker (and Kubernetes) containers.
Unfortunately, Portainer is not open-source. However, it's the best of its kind of software that I've found so far.
The Portainer instance is protected by Cloudflare Access and requires two-factor authentication to access.
Portainer runs as a single Docker container using the
portainer/portainer-ce:latest image. Here is the Docker Compose service entry for it:
services: portainer: container_name: portainer image: portainer/portainer-ce:latest restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock - /srv/portainer/data:/data networks: - default - swag networks: swag: name: swag_default external: true
Docker socket volume
Since Portainer needs to be able to read and modify the state of the Docker engine, it requires access to the Docker socket file. This is mounted just like any other volume:
volumes: - /var/run/docker.sock:/var/run/docker.sock
Portainer stores some persistent data. In the Docker container, this is located at
/data, so we mount a Docker volume there:
volumes: - /srv/portainer/data:/data
All configuration is done within Portainer itself. It has a complete settings interface.
Single Sign On with Authentik
Portainer has the ability to interface with an OpenID Connect provider like Authentik.
Configuring SSO in Portainer
The relevant settings are confiured in the Authentication section of the Settings interface. Select the OAuth card for the Authentication method option. See the following table for the rest of the settings:
|Use SSO||✓||Enable single sign-on|
|Hide internal authentication prompt||✓||Only use SSO for logins, not Portainer's built-in system|
|Automatic user provisioning||✓||Automatically create new users when they first log in. This is safe if (1) you trust all users who can log in to Portainer using SSO, or (2) you don't give new users write access to resources in Portainer.|
|Automatic team membership||✓||Assign users to Teams based on the groups they belong to within Authentik|
||The claim in which Authentik places the list of groups|
|Statically assigned teams||Whatever you want||Use this field to map from Authentik groups to Portainer teams. You must create the team in Portainer before you can select it here.|
||Don't assign normal users who aren't part of a privileged group to a team|
|Assign admin rights to groups||✓||Automatically assign administrator permissions to certain users|
|Admin mapping claim value regex||
||Give members of the
In the Provider section, select the Custom card. See the following table for the settings' values:
|Client ID||Client ID created by Authentik||Sets the OpenID client ID|
|Client Secret||Client Secret created by Authentik||Sets the OpenID client secret for authenticating with Authentik|
||OpenID authorization endpoint|
|Access token URL||
||OpenID authorization endpoint|
||OpenID user information resource endpoint|
||The URL Authentik will redirect t o after successful authentication|
||The URL Portainer will redirect to when logging out|
||Defines what field Portainer will use to map Portainer users to Authentik users. If usernames are controlled and static, it is safe to use
||The OpenID user info scopes that Portainer will request from Authentik|
Configuring SSO in Authentik
On the Authentik side, an Application and an OpenID Provider must be created.
For the Redirect URI option, use the base URL of the Portainer instance, in our case
All other options should be fine when left with their default values.
Stack environment variables
When defining environment variables for a Docker Compose stack in Portainer, the variables will be accessible within the docker compose file as if defined in a
.env file when using the
docker compose command.
The variables will also be written to a
stack.env file, so they can be loaded into a container's environment be adding the following line to the service entry for that container:
Docker Compose build contexts
When building a container in a Docker Compose stack, it is not possible to use a path on the host as the build context (i.e. where the
Dockerfile is located).
This is different from defining volumes, which use paths on the host, not inside the Portainer container.
To get around this, either mount the build context path in the Portainer container, or use a non-file context like a Git repository.