@Wonderfall J'hésite sur la compréhension d'un point pour les réseaux sur Traefik. Imaginons que j'ai 3 applis à faire passer par Traefik. Il faut donc que je crée seulement 3 réseaux différents (tous external, un par app) ou 4 réseaux (tous external, un par app + un pour Traefik) ? Je pense que le réseau 4 est inutile si j'ai bien compris.
En résumé :

  • Réseau1 (external) : Traefik + App1
  • Réseau2 (external) : Traefik + App2
  • Réseau3 (external) : Traefik + App3
  • Réseau4 (external) : Traefik -> ?

Et s'il faut le réseau 4 comment Traefik sait qu'il doit être connecté à l'extérieur par celui-là ? C'est à déclarer dans traefik.yml en providers: docker: network: ? Merci !

Edit : Et d'ailleurs dans chaque docker-compose qui a plusieurs réseaux déclarés il faut lui préciser lequel est à utiliser pour Traefik ?

    NicCo Oui j'ai pas très bien compris, mais le 4ème réseau sera inutile du coup.
    Traefik utilise ce label par app que tu veux exposer : traefik.docker.network=mon_reseau

    @Wonderfall Oui difficile à expliquer mais en gros il ne faut pas que je crée un réseau où il y aura juste traefik tout seul dedans. Donc dans le cas où j'ai 3 apps avec chacun leur réseau dédié, je déclare ces 3 réseaux dans le docker-compose de traefik. Mais comment savoir lequel des 3 doit être utilisé par traefik pour sortir ? J'en prends un au hasard vu qu'ils sont tous external ?
    Et on est obligé de passer par les labels ? On ne peut pas déclarer soit dans le fichier yaml de config statique de traefik, soit dans le fichier yaml de config des services/routers de chaque app ?
    Merci.

      NicCo Un réseau external te donne la connectivité, mais à partir de là tu map Traefik aux ports de l’hôte directement. Le label que j’ai donné est à préciser pour chaque conteneur pour que Traefik sache sur quel réseau il doit trouver ce conteneur. Comme dit, moi j’ai juste pour le moment un gros réseau frontend.

      Chez Traefik tu as différents backends (Docker, file, etc.) et types de configuration (dynamique/statique, labels/toml/yaml). Donc tout ce que tu peux faire en label tu peux le faire en statique yaml et vice versa. La documentation couvre vraiment beaucoup, n’hésite pas à la consulter !

      @Wonderfall Merci, j'ai regardé la doc de traefik et j'ai fouillé un peu sur Google mais difficile de trouver quelqu'un qui a mis en place un réseau par app.
      Du coup je ne sais pas trop quoi comme réseau pour traefik quand il y a plusieurs apps avec un réseau chacun.

      App1 :

      version: "2.4"
      
      networks:
        network1:
          external: true
      
      services:
        app1:
          container_name: app1
          image: app/app1
          labels:
            - traefik.docker.network=network1
          networks:
            - network1
          restart: unless-stopped

      App2 :

      version: "2.4"
      
      networks:
        network2:
          external: true
      
      services:
        app2:
          container_name: app2
          image: app/app2
          labels:
            - traefik.docker.network=network2
          networks:
            - network2
          restart: unless-stopped

      App3 :

      version: "2.4"
      
      networks:
        network3:
          external: true
      
      services:
        app3:
          container_name: app3
          image: app/app3
          labels:
            - traefik.docker.network=network3
          networks:
            - network3
          restart: unless-stopped

      Traefik :

      version: "2.4"
      
      networks:
        network1:
          external: true
        network2:
          external: true
        network3:
          external: true
      
      services:
        traefik:
          container_name: traefik
          image: traefik
          volumes:
            - ./traefik.yml:/etc/traefik/traefik.yml
            - ./acme/acme.json:/etc/traefik/acme.json
            - ./certs:/etc/traefik/certs
            - ./conf.d:/etc/traefik/conf.d
            - /var/run/docker.sock:/var/run/docker.sock
          ports:
            - 80:80
            - 443:443
          networks:
            - network1
            - network2
            - network3
          restart: unless-stopped

      Avec ce genre d'environnement, normalement je dois rajouter dans le fichier de configuration traefik.yml quel réseau doit être utilisé par traefik non ? Sur les autres exemples que je trouve un peu partout c'est toujours "web" ou "frontend" donc un seul réseau pour tous, mais dans le cas de plusieurs networks je ne vois pas lequel indiquer dans la conf de traefik :

      providers:
        docker:
          network: network1 # ou network2 ou network3

      La doc de traefik indique bien

      Defines a default docker network to use for connections to all containers.

      Mais tu as essayé comme ça ? Tu ne devrais pourtant pas avoir à préciser de réseau pour le provider Docker. Pour moi ça devrait fonctionner si tu précises par app le label Traefik du réseau à utiliser.

      Sinon c'est effectivement un cas très rare, d'habitude on fait un gros réseau frontend avec le provider Docker, rapide et simple mais isole moins les apps entre elles (ça pose problème si tu dépends par exemple d'une basicauth donc via le proxy pour sécuriser l'accès à une application).

      Cependant sache qu'il n'y a aucun problème si utilises des configurations statiques, même sans forcément les IP statiques (c'est juste pour gVisor ça, t'embête pas comme moi) ; donc au pire des cas, fais de la configuration statique directement avec l'exemple que je t'avais fourni par mail (ou celui de xataz). Mais je suis persuadé qu'avec juste les labels de réseau ça devrait marcher, ça me semblait logique (mais si ce n'est pas le cas excuse-moi).

      @Wonderfall Non je n'ai pas encore essayé comme ça, je vais essayer de mettre en place Traefik et les apps pour tester. C'était simplement pour comprendre le fonctionnement de la chose, vu que je n'ai pas réussi jusqu'à maintenant à trouver un cas d'utilisation à plusieurs réseaux 😉 (à se demander si Traefik est prévu pour fonctionner ainsi) et vu que la doc indique "un réseau par défaut pour les connections de tous les containeurs" je me posais la question. Mais je vais tester, de toutes façons si ça ne fonctionne pas ça devrait se voir rapidement...

      Pour les IP statiques ce n'est pas un problème, j'ai déjà établi un plan d'adressage IP avec tous les réseaux etc donc tant qu'à faire je vais partir sur ça 🙂 si ça ne fonctionne pas en label je testerai en statique mais je ne pense pas que ce soit qui fasse la différence (et pas d'excuse à avoir, avec tout ce que tu m'aides et puis c'est l'occasion de tester)

      @Wonderfall Pour le moment ça a l'air de fonctionner, j'en profite aussi pour tester le proxy socket qui fonctionne aussi (par contre pour Portainer par exemple il faut activer plusieurs variables d'environnement, j'espère que niveau sécurité ça ne pose pas de souci mais pas le choix sinon à priori)

      Par contre j'ai une question sur l'utilisation du socket sur Traefik. Sur la version basique que j'utilisais je ne l'avais pas renseigné dans providers (donc Traefik ne l'utilisait pas) mais ça ne semble pas lui poser de souci puisque ça fonctionnait. A quoi sert l'utilisation du socket sur Traefik ? Juste à surveiller les containeurs qui ont un lien avec Traefik ? Parce que j'ai remarqué aussi que depuis que je l'ai activé, j'ai les services et routers en double pour un container, un en provider "file" et l'autre en provider "docker". Si je n'ai pas besoin de l'activer, je m'en passerai.

      Rule | Entrypoints | Name | Service | Provider
      Host(portainer-portainer) | web websecure | portainer-portainer@docker | portainer-portainer | Docker
      Host(portainer.domain.tld) | websecure | portainer-secure@file | portainer@file | File

      Pour le moment ça a l'air de fonctionner

      Avec les labels pour chaque réseau ? Cool du coup !

      j'en profite aussi pour tester le proxy socket qui fonctionne aussi (par contre pour Portainer par exemple il faut activer plusieurs variables d'environnement, j'espère que niveau sécurité ça ne pose pas de souci mais pas le choix sinon à priori)

      Non c'est normal, effectivement Portainer a besoin d'infos supplémentaires qui sont cachées par socket-proxy par défaut. Cependant n'oublie pas que socket-proxy empêche les requêtes POST, donc l'utilité de Portainer en dehors de visionner ses conteneurs est discutable. (Pour ma part je n'aime pas utiliser Portainer.)

      A quoi sert l'utilisation du socket sur Traefik ?

      Le provider comme son nom l'indique fournit à Traefik informations et configurations de ce qu'il doit faire. Le socket comme provider est parfait pour du plug & play avec les conteneurs, tu peux ajouter/retirer des conteneurs à la volée et Traefik le prendra en compte.

      En soit, j'ai aussi des providers docker et file. Docker pour fournir les configurations de mes conteneurs, File pour les configurations style les headers HSTS que j'appelle dans le compose via "@file". Effectivement tu as l'air d'avoir du doublon par contre, si tu mix labels/config statique pour les conteneurs j'imagine que ça peut arriver, je sais pas trop comment tu t'y es pris au final

        Wonderfall Pour le moment, j'ai ajouté un
        docker:
        network:
        (nomdureseau)
        dans les configs dynamiques (conf.d) pour chaque app (fichiers yaml). Désolé pour la syntaxe je suis sur téléphone.

        Pour Portainer, je ne m'en sers pas pour déployer avec mais j'aime bien pour avoir une vue sur mes containers, réseaux, etc... S'il y a mieux je suis preneur 😉

        Et niveau config je crée dans conf.d un fichier yaml pour chaque app. Dans ces fichiers je déclare les routers et services en utilisant @file donc je pense qu'il doit me charger via le provider @file et via le provider docker. Mais du coup ce n'est pas la bonne façon de faire ? Il ne faut pas ajouter déclarer les routers/services dans des fichiers dans conf.d ? Ou il ne faut pas utiliser @file ? Si tu as un exemple je suis preneur, je me suis basé sur l'exemple du 1er post en l'adaptant (peut-être mal). Merci !

        Il n'y a pas de "bonne" façon, avec Traefik il y a des façons de faire.
        Ben du coup si tu n'utilises pas du tout Docker comme provider, désactive-le ou alors active désactive "exposedByDefault" comme indiqué dans la doc : https://doc.traefik.io/traefik/providers/docker/

        (Dis mois si ça marche, je serai curieux.)

        Pour Portainer, si tu veux monitorer il y a de meilleurs outils pour ça. Netdata pour du temps-réel, cAdvisor + Prometheus si tu veux vraiment sortir les gros moyens.

          Wonderfall Je vais tester ça je te tiens au courant. Mais si je désactive docker comme provider ça revient simplement à retirer le socket de ma config, c'est la seule chose que j'ai de configuré dans la section docker.

          Et concernant Portainer, c'est surtout la vue des containers, des réseaux, des stacks, etc enfin tout ce qui concerne Docker, je ne sais pas si c'est possible sur Netdata que je vois plutôt comme une supervision basique (je ne l'ai pas encore testé, il faut que je m'y mette)

          @Wonderfall Je viens de tester et effectivement le exposedByDefault permet de supprimer les doublons, il ne me reste du coup que les routers/services déclarés dans les fichiers des apps. J'arrive au même résultat que si je supprime entièrement le provider docker.
          En résumé :

          global:
            checkNewVersion: false
            sendAnonymousUsage: false
          
          providers:
            docker:
              endpoint: "tcp://xxx.xxx.xxx.xxx:2375"
              exposedByDefault: false
            file:
              directory: /etc/traefik/conf.d/
              watch: true
          
          api:
            dashboard: true

          Me donne le même résultat que :

          global:
            checkNewVersion: false
            sendAnonymousUsage: false
          
          providers:
            file:
              directory: /etc/traefik/conf.d/
              watch: true
          
          api:
            dashboard: true

          Par contre si je ne mets pas le exposedByDefault: false j'ai des doublons.

          Un exemple de fichier d'app dans conf.d : portainer.yml

          docker:
            network: test1
          
          http:
            services:
              portainer:
                loadBalancer:
                  servers:
                    - url: "http:/xxx.xxx.xxx.xxx:9000"
          
          routers:
            portainer-secure:
              rule: "Host(`portainer.domain.tld`)"
              entryPoints:
                - "websecure"
              middlewares:
                - "hsts@file"
                - "security@file"
                - "compression@file"
              service: "portainer@file"
              tls:
                certResolver: letsencrypt-ec384

          Et on retombe sur ce que j'ai indiqué plus haut, sans le exposedByDefault j'ai un doublon qui n'a pas le même nom, pas de TLS, qui a un entrypoint web en plus et dont le provider est docker (au lieu de file)

            NicCo Oui ça revient exactement au même, si tu mets le exposedByDefault sur false il va s'en foutre du conteneur sauf si tu mets un label qui l'active "traefik.enable=true" ou qqchose du genre.

            @Wonderfall Du coup j'ai converti mon fichier portainer.yml en labels à l'identique du fichier de config dynamique (sauf url qui n'est pas supporté dans les labels) et maintenant je n'ai plus de doublon malgré l'activation du traefik.enable, ce qui est normal vu que j'ai supprimé le fichier portainer.yml après la transformation en labels :

            labels:
              - "traefik.enable=true"
              - "traefik.docker.network=test1"
              - "traefik.http.routers.portainer-secure.rule=Host(`portainer.domain.tld`)"
              - "traefik.http.routers.portainer-secure.entrypoints=websecure"
              - "traefik.http.routers.portainer-secure.middlewares=hsts@file, security@file, compression@file"
              - "traefik.http.routers.portainer-secure.tls.certresolver=letsencrypt-ec384"
              - "traefik.http.routers.portainer-secure.service=portainer"
              - "traefik.http.services.portainer.loadBalancer.server.port=9000"

            Mais en faisant ça maintenant le provider docker pour portainer récupère les bonnes informations :

            TLS | Rule | Entrypoints | Name | Service | Provider
            True | Host(portainer.domain.tld) | websecure | portainer-secure@docker | portainer | Docker

            Je ne sais pas si je loupe quelque chose dans le fichier de config dynamique. Après si je passe en labels, quels sont les avantages/inconvénients par rapport à une config dynamique ? Si je comprends bien le tuto de @xataz :

            Déjà je n'aime pas le fait de mettre mon socket docker dans un conteneur, même en lecture seul, le socket à toutes les informations des conteneurs. Autrement, je n'aime pas trop alourdir mes docker-compose, j'aime quand c'est clair, net et précis.

            Le fait de passer par les fichiers de config permet de (1) ne pas à avoir à utiliser le socket docker dans traefik et (2) ne pas surcharger les docker-compose avec tous les labels ?

            Edit : Le maintainer de Traefik conseille d'utiliser les labels avec Docker : https://community.traefik.io/t/label-vs-yml-config-setup/3546
            Vu que je vais utiliser le socket proxy avec, ce sera déjà un peu plus secure si j'utilise le socket dans traefik

              NicCo Tu m'as perdu, pourquoi vouloir utiliser la configuration dynamique du coup ?
              Je réitère qu'il n'y a pas de meilleur choix, ça dépend de ce que tu veux, de ton usage, tes besoins. Pour moi xataz a raison, si tu joues pas avec tes conteneurs toutes les semaines autant tout mettre dans la config statique. Si c'était le doublon le problème, quel était le souci d'utiliser la config statique avec exposeByDefault sur false (ou sans le provider Docker du tout) ?

              A mon avis tu te prends beaucoup trop la tête. 😅
              Maintenant, oui, le provider Docker/config dynamique avec socket-proxy c'est déjà bien mieux que monter le socket en nature.

                Wonderfall En fait j'ai débuté Docker réellement il y a un mois donc je suis encore en phase de découverte (vu l'étendue des possibilités) et je ne suis pas forcément fixé sur une manière de faire ou l'autre 😉 je suis parti sur la configuration dynamique vu que c'est ce qui est utilisé dans le tuto, mais le tuto aurait utilisé les labels je serais parti sur les labels 😆
                Vu que je pars de zéro j'essaye de voir les possibilités que j'ai pour pouvoir faire les choses, du coup je regarde, je teste et comme j'aime bien comprendre je pars un peu dans tous les sens, je suis d'accord avec toi je me prends beaucoup la tête 😅
                Donc pour l'histoire des doublons par exemple je cherche pourquoi le résultat du provider docker n'est pas le même selon ce qui est utilisé alors que tu as raison je peux laisser le exposedByDefault à false ou sans provider Docker.
                Maintenant j'aime bien les 2 façons de faire (labels ou file), j'aime bien les labels car tout est dans le même fichier pour l'app (docker-compose + traefik) mais ça oblige à fournir un accès à la socket. Le file permet de se passer du socket mais la config traefik est en dehors du docker-compose, les 2 se tiennent. Je pense que si j'arrive à me passer du socket sur les autres containers, je partirais en file, si je dois monter la socket (et donc la proxyfier) je partirai en labels 😉

                6 jours plus tard

                @Wonderfall I'm back 🙂 est-ce que tu pourrais m'expliquer à quoi sert "whoami" si tu sais ? Je suis en train de regarder pour mettre en place authelia et je vois que dans leur docker-compose ils créent 2 apps accessibles depuis l'extérieur (public.domain.tld ou secure.domain.tld). De ce que je comprends, à priori ça donne des infos sur la machine sur laquelle il est déployé, mais je ne vois pas l'intérêt de le publier sur Internet. A moins que ce soit pour tester le bon fonctionnement d'authelia ? Merci !

                Salut, oui whoami c'est juste une image qui sert d'exemple ! Inutile de la déployer du coup

                9 mois plus tard

                Super tuto !
                J'essaye d'implémenter le port forwading sur le service SSH. En effet, j'ai plusieurs conteneurs derrière Traefik et je souhaiterais que en faisant un ssh user@instance1.domain -p xxxxx, je sois forwadé sur le port ssh de l'instance conteneur en question, ainsi de suite.
                J'ai ajouté un entrypoints sur le port SSH (22)

                Voici un extrait de mon fichier yml pour l'instance1
                labels:
                - "traefik.enable=true"
                - "traefik.tcp.routers.ssh.entrypoints=ssh"
                - "traefik.tcp.routers.ssh.service=ssh"
                - "traefik.tcp.routers.ssh.rule=HostSNI(
                instance1.domain)"
                - "traefik.tcp.services.ssh.loadbalancer.server.port=22"
                - "traefik.tcp.routers.ssh.tls=true"

                Avec cette configuration, dépuis un hôte externe quand j'essaie de me connecter, je reçois cette erreur : kex_exchange_identification: Connection closed by remote host