Post

Portainer - administration des conteneurs Docker

Portainer - administration des conteneurs Docker

Portainer CE est une application gratuite et open source destinée à simplifier l’administration des conteneurs Docker et des environnements basés sur des micro-services. Cette solution d’administration accessible à partir d’un navigateur Web se veut à la fois pratique et conviviale. Au-delà de la présentation de cette solution, cet article explique comment installer Portainer et comment l’utiliser pour administrer ses conteneurs Docker

  • Administration via interface Web
  • Gestion de plusieurs environnements (Docker Standalone, Docker Swarm, Kubernetes, etc.)
  • Déploiement d’applications via des stacks Docker Compose et des modèles
  • Gestion complète des conteneurs Docker : containers, images, volumes, networks, etc.
  • Visualisation précise de l’état des ressources : CPU, RAM, stockage, statuts des conteneurs
  • Actions quotidiennes sur les conteneurs : démarrer, arrêter, redémarrer, logs, etc.
  • Éditeur de fichiers Docker Compose intégré
  • Gestion des utilisateurs, des groupes et des équipes
  • Gestion des registres d’images, avec l’intégration native du Docker Hub

    Portainer central

docker-compose

docker-compose.yml (Portainer central) — utilise vos certificats et expose uniquement HTTPS 9443 via nginx reverse proxy (Portainer écoute en interne sur 9443) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
version: "3.8"
services:
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    command: -H unix:///var/run/docker.sock
    volumes:
      - portainer_data:/data
      - /var/run/docker.sock:/var/run/docker.sock
    restart: always

  nginx:
    image: nginx:stable
    container_name: portainer_nginx
    ports:
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - /etc/ssl/private/portainer.home.arpa.crt:/etc/ssl/certs/portainer.crt:ro
      - /etc/ssl/private/portainer.home.arpa.key:/etc/ssl/private/portainer.key:ro
    depends_on:
      - portainer
    restart: always

volumes:
  portainer_data:

Lancez votre stack

1
docker compose up -d

Proxy nginx

nginx site config (/etc/nginx/conf.d/portainer.home.arpa.conf)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
    listen 443 ssl;
    server_name portainer.home.arpa;

    ssl_certificate     /etc/ssl/certs/portainer.crt;
    ssl_certificate_key /etc/ssl/private/portainer.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass         http://portainer:9443;
        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;
        proxy_http_version 1.1;
        proxy_set_header   Connection "";
        proxy_read_timeout  90;
    }
}

Recharger nginx

1
sudo systemctl reload nginx

Connexion

Ouvrir l’UI https://portainer.home.arpa, créez l’admin et mot de passe.

Authentification OAuth

Settings –> Authentication: OAuth

Authelia - Configuration client portainer

Générer un client_secret via la commande suivante :

1
2
3
authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986

La commande précédente renvoie 2 lignes

1
2
3
4
5
Random Password: -G3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Digest: $pbkdf2-sha512xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

⚠️ Veuillez noter le mot de passe en clair (Random Password) ainsi que le hachage $pbkdf2 (Digest) du mot de passe pour une utilisation ultérieure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    clients:
      - client_id: 'portainer'
        client_name: 'Portainer'
        client_secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng'  # The digest of 'insecure_secret'.
        public: false
        authorization_policy: 'two_factor'
        require_pkce: false
        pkce_challenge_method: ''
        redirect_uris:
          - 'https://portainer.home.arpa'
        scopes:
          - 'openid'
          - 'profile'
          - 'groups'
          - 'email'
        response_types:
          - 'code'
        grant_types:
          - 'authorization_code'
        access_token_signed_response_alg: 'none'
        userinfo_signed_response_alg: 'none'
        token_endpoint_auth_method: 'client_secret_post'

Portainer - OAuth

Pour configurer Portainer pour utiliser Authelia en tant que fournisseur OpenID Connect 1.0, utilisez les instructions suivantes:

Settings –> Authentication –> Authentication Method: OAuth

  • Provider: Custom
  • Automatic User Provision: Enable if you want users to automatically be created in Portainer.
  • Client ID: portainer
  • Client Secret: insecure_secret
  • Authorization URL: https://auth.rnmkcy.eu/api/oidc/authorization
  • Access Token URL: https://auth.rnmkcy.eu/api/oidc/token
  • Resource URL: https://auth.rnmkcy.eu/api/oidc/userinfo
  • Redirect URL: https://portainer.home.arpa
  • User Identifier: preferred_username
  • Scopes: openid profile groups email
  • Auth Style: In Params

Créer un utilisateur qui est reconnu par Authelia OIDC (pour info les utilisateurs Authelia sont gérés par un serveur LLDAP)

Connexion via OAuth

Déploiement des agents portainer

Manuellement

Si vous avez plusieurs machines qui servent à héberger vos conteneurs, sachez qu’il est possible de contrôler Docker sur celles-ci depuis une interface unique, sans avoir besoin de déployer Portainer sur chacune.

Il faudra bien entendu déployer un composant sur chaque machine, mais uniquement un conteneur Portainer Agent, plus léger.

Voici la commande à utiliser pour lancer cet agent :

1
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

Ou avec une stack docker compose :

1
2
3
4
5
6
7
8
9
10
11
12
services:
  portainer-agent:
    container_name: portainer_agent
    image: portainer/agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes
    labels:
      - com.centurylinklabs.watchtower.enable=true
    ports:
      - 9001:9001
    restart: always

Auto via script

script prêt à l’emploi qui lit votre fichier CSV (format NAME;USER,IP,PORT;SSH_KEY), déploie le Portainer Agent sur chaque hôte en utilisant la clé SSH correspondante, et vérifie l’état. Le script gère clés différentes par hôte et ports personnalisés.

Création fichier hosts.csv avec une ligne par hôte

cwwk;yick,192.168.0.205,55205;$HOME/.ssh/yick-ed25519
alpine02;rad,192.168.0.222,55222;$HOME/.ssh/pvm-alpine02
alpine03;alpi,192.168.0.223,55223;$HOME/.ssh/pvm-alpine03

le script fonctionne pour Debian et Alpine dans la majorité des cas, mais quelques ajustements/ vérifications sont nécessaires car les images et environnements peuvent différer. Résumé des points à couvrir et version adaptée du script qui gère Debian/Alpine (teste la présence de docker, utilise sudo si nécessaire, installe Docker Engine si absent — optionnel).

Choses à vérifier/adapter par hôte

  • Présence de Docker (docker CLI & daemon). Si absent, le script peut proposer d’installer Docker (diffère Debian vs Alpine).
  • Si l’utilisateur SSH nécessite sudo pour exécuter docker, exécuter docker via sudo (et s’assurer que sudo n’exige pas de mot de passe).
  • Sur Alpine, le binaire docker peut être fourni par package docker (apk add docker) et le service docker doit être démarré (service docker start) — parfois l’install diffère.
  • Présence de firewall/ports (9001 exposé localement). Le script publie 9001:9001 sur l’hôte, ce qui est standard.
  • Permissions du socket /var/run/docker.sock (l’utilisateur doit pouvoir l’utiliser ou utiliser sudo).

Script amélioré (gère Debian/Alpine, vérifie docker, option d’install, support sudo)

  • Sauvegardez en deploy_agents_flexible.sh et rendez exécutable.

Script deploy_agents_flexible.sh (placez à côté de hosts.csv, rendez exécutable)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/env bash
set -euo pipefail

HOSTS_FILE="${1:-hosts.csv}"
AGENT_IMAGE="${AGENT_IMAGE:-portainer/agent:latest}"
TMPDIR="${TMPDIR:-/tmp}"
SSH_OPTS="-o StrictHostKeyChecking=accept-new -o BatchMode=yes -o ConnectTimeout=10"
INSTALL_IF_MISSING="${INSTALL_IF_MISSING:-no}"   # set to yes to attempt install docker remotely
USE_SUDO_IF_REQUIRED="${USE_SUDO_IF_REQUIRED:-yes}" # try sudo if docker not runnable

if [ ! -f "$HOSTS_FILE" ]; then
  echo "Hosts file not found: $HOSTS_FILE" >&2
  exit 1
fi

while IFS= read -r line || [ -n "$line" ]; do
  [[ -z "$line" || "${line:0:1}" == "#" ]] && continue

  NAME=$(echo "$line" | awk -F';' '{print $1}')
  second=$(echo "$line" | awk -F';' '{print $2}')
  ssh_key_field=$(echo "$line" | awk -F';' '{print $3}')
  IFS=',' read -r USER IP PORT <<< "$second"
  eval "SSH_KEY_PATH=${ssh_key_field}"

  echo "=> [$NAME] ${USER}@${IP}:${PORT} key=${SSH_KEY_PATH}"

  if [ ! -f "$SSH_KEY_PATH" ]; then
    echo "   ERROR: SSH key not found: $SSH_KEY_PATH" >&2
    continue
  fi

  ssh -i "$SSH_KEY_PATH" $SSH_OPTS -p "$PORT" "$USER@$IP" bash -s -- "$AGENT_IMAGE" "$INSTALL_IF_MISSING" "$USE_SUDO_IF_REQUIRED" <<'REMOTE'
set -e
AGENT_IMAGE="$1"
INSTALL_IF_MISSING="$2"
USE_SUDO_IF_REQUIRED="$3"

# helper to run docker, try without sudo then with sudo if allowed
run_docker() {
  if docker version >/dev/null 2>&1; then
    docker "$@"
    return 0
  fi
  if [ "$USE_SUDO_IF_REQUIRED" = "yes" ] && sudo -n docker version >/dev/null 2>&1; then
    sudo docker "$@"
    return 0
  fi
  return 1
}

# ensure docker present (optional)
if ! run_docker version >/dev/null 2>&1; then
  echo "Docker not available."
  if [ "$INSTALL_IF_MISSING" = "yes" ]; then
    # detect distro
    if [ -f /etc/os-release ]; then
      . /etc/os-release
      case "$ID" in
        alpine)
          echo "Installing docker on Alpine..."
          sudo apk update
          sudo apk add --no-cache docker
          sudo rc-update add docker boot || true
          sudo service docker start
          ;;
        debian|ubuntu)
          echo "Installing docker on Debian/Ubuntu..."
          sudo apt-get update
          sudo apt-get install -y ca-certificates curl gnupg lsb-release
          curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
          echo \
            "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
            $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
          sudo apt-get update
          sudo apt-get install -y docker-ce docker-ce-cli containerd.io
          sudo systemctl enable docker --now || true
          ;;
        *)
          echo "Unsupported distro for automatic install: $ID" >&2
          exit 1
          ;;
      esac
    fi
    # re-check
    if ! run_docker version >/dev/null 2>&1; then
      echo "Docker still not available after install attempt." >&2
      exit 1
    fi
  else
    echo "Set INSTALL_IF_MISSING=yes to attempt automatic install of Docker." >&2
    exit 1
  fi
fi

echo "Using docker to pull and run agent..."
if run_docker pull "$AGENT_IMAGE"; then
  echo "Pulled $AGENT_IMAGE"
else
  echo "Failed to pull $AGENT_IMAGE" >&2
fi

# remove existing container if present
if run_docker rm -f portainer_agent 2>/dev/null; then
  echo "Removed old container"
fi

# run the agent (publish 9001)
run_docker run -d --name portainer_agent --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /var/lib/docker/volumes:/var/lib/docker/volumes \
  -p 9001:9001 \
  "$AGENT_IMAGE"

echo "Agent started."
REMOTE

  echo "   [$NAME] done."
done < "$HOSTS_FILE"

echo "All done."

Rendre exécutable et lancer

1
2
chmod +x deploy_agents_flexible.sh
./deploy_agents_flexible.sh hosts.csv

Les agents sont déployés sur les distants

Vérifier avec la commande ssh

1
2
3
4
5
6
7
8
9
10
11
12
13
ssh yick@192.168.0.205 -p 55205 -i /home/yann/.ssh/yick-ed25519 docker ps |grep portainer
# Portainer hôte
cf52f3ed0ea9   portainer/portainer-ce:latest                                    "/portainer"             2 hours ago   Up 2 hours                                                          portainer
# portainer agent
339f93b6aa1f   portainer/agent:latest                                           "./agent"                3 hours ago   Up 3 hours            0.0.0.0:9001->9001/tcp, [::]:9001->9001/tcp   portainer_agent
#---------------------
ssh -p 55222 -i /home/yann/.ssh/pvm-alpine02 rad@192.168.0.222 docker ps |grep portainer
# portainer agent
2d10bbdf01a9   portainer/agent:latest                         "./agent"                3 hours ago    Up 3 hours            0.0.0.0:9001->9001/tcp, [::]:9001->9001/tcp                                          portainer_agent
#---------------------
ssh alpi@192.168.0.223 -p 55223 -i /home/yann/.ssh/pvm-alpine03 docker ps |grep portainer
# portainer agent
975141ccde49   portainer/agent:latest                                     "./agent"                3 hours ago    Up 3 hours            0.0.0.0:9001->9001/tcp, [::]:9001->9001/tcp   portainer_agent

Portainer configuration

Web UI

Passons maintenant à la configuration dans Portainer. Rendez-vous dans “Environments” et cliquez sur “Add Environment”.

Par défaut, c’est l’environnement “Portainer agent” qui est sélectionné. Donnez un nom à l’environnement que vous souhaitez ajouter, renseignez l’adresse IP de l’hôte et le port de l’agent Portainer sous la forme “IP.HOTE.DOCKER:PORT”. Cliquez enfin sur “Add Environment” en bas de page pour sauvegarder.

Après lancement (2)
Sélection “Agent”

Nouvel environnement ajouté

Cet article est sous licence CC BY 4.0 par l'auteur.