Skip to content

Portainer

Tip

Some time after originally publishing this recipe, I had the opportunity to meet the Portainer team, who are based out of Auckland, New Zealand. We now have an ongoing friendly working relationship. Portainer is my GitHub Sponsor ❤, and in return, I maintain their official Kubernetes helm charts! 👍

Portainer is a lightweight sexy UI for visualizing your docker environment. It also happens to integrate well with Docker Swarm clusters, which makes it a great fit for our stack.

Portainer attempts to take the "geekiness" out of containers, by wrapping all the jargon and complexity in a shiny UI and some simple abstractions. It's a great addition to any stack, especially if you're just starting your containerization journey!

Portainer Screenshot

Ingredients

Ingredients

Already deployed:

Related:

  • Traefik Forward Auth to secure your Traefik-exposed services with an additional layer of authentication

Preparation

Setup data locations

Create a folder to store portainer's persistent data:

mkdir /var/data/portainer

Setup Docker Swarm

Create a docker swarm config file in docker-compose syntax (v3), something like this:

Tip

I automatically and instantly share (with my sponsors) a private "premix" git repository, which includes necessary docker-compose and env files for all published recipes. This means that sponsors can launch any recipe with just a git pull and a docker stack deploy 👍.

🚀 Update: Premix now includes an ansible playbook, so that sponsors can deploy an entire stack + recipes, with a single ansible command! (more here)

version: '3.2'

services:
  portainer:
    image: portainer/portainer-ce
    command: -H tcp://tasks.agent:9001 --tlsskipverify
    ports:
      - "9000:9000"
      - "8000:8000"
    volumes:
      - /var/data/portainer:/data
    networks:
      - internal
      - traefik_public
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]
      labels:
        # traefik
        - traefik.enable=true
        - traefik.docker.network=traefik_public

        # traefikv1
        - traefik.frontend.rule=Host:portainer.example.com
        - traefik.port=9000    
        # uncomment if you want to protect portainer with traefik-forward-auth using traefikv1 
        # - traefik.frontend.auth.forward.address=http://traefik-forward-auth:4181
        # - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User
        # - traefik.frontend.auth.forward.trustForwardHeader=true        

        # traefikv2
        - "traefik.http.routers.portainer.rule=Host(`portainer.example.com`)"
        - "traefik.http.routers.portainer.entrypoints=https"
        - "traefik.http.services.portainer.loadbalancer.server.port=9000"
        # uncomment if you want to protect portainer with traefik-forward-auth using traefikv2
        # - "traefik.http.routers.portainer.middlewares=forward-auth"

  agent:
    image: portainer/agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes
    networks:
      - internal
    deploy:
      mode: global
      placement:
        constraints: [node.platform.os == linux]

networks:
  traefik_public:
    external: true
  internal:
    driver: overlay
    ipam:
      config:
        - subnet: 172.16.13.0/24

Note

Setup unique static subnets for every stack you deploy. This avoids IP/gateway conflicts which can otherwise occur when you're creating/removing stacks a lot. See my list here.

Umm.. didn't you just copy these from the official Portainer docs?

Almost word-for-word! I've made a few (opinionated) improvements though:

  • Expose Portainer via Traefik with valid LetsEncrypt SSL certs
  • Optionally protected Portainer's web UI with OIDC auth via Traefik Forward Auth
  • Use filesystem paths instead of Docker volumes for maximum "swarminess" (We want an HA swarm, and HA Docker Volumes are a PITA, so we just use our ceph shared storage)

Serving

Launch Portainer stack

Launch the Portainer stack by running docker stack deploy portainer -c <path -to-docker-compose.yml>

Log into your new instance at https://YOUR-FQDN. You'll be prompted to set your admin user/password on first login. Start at "Home", and click on "Primary" to manage your swarm (you can manage multiple swarms via one Portainer instance using the agent):

Portainer Home

Chef's notes 📓


  1. There are some schenanigans you can do to install LinuxServer.io templates in Portainer. Don't go crying to them for support though! 😿 

Tip your waiter (sponsor) 👏

Did you receive excellent service? Want to make your waiter happy? (..and support development of current and future recipes!) Sponsor me on Github / Patreon, or see the contribute page for more (free or paid) ways to say thank you! 👏

Flirt with waiter (subscribe) 💌

Want to know now when this recipe gets updated, or when future recipes are added? Subscribe to the RSS feed, or leave your email address below, and we'll keep you updated. (*double-opt-in, no monkey business, no spam)

Notify me 🔔

Be the first to know when recipes are added / improved!

    We won't send you spam. Unsubscribe at any time. No monkey-business.

    Powered By ConvertKit

    Your comments? 💬


    Last update: October 21, 2021
    Back to top