Docker: Routage HTTPS

Comment gérer le routage HTTP et le chiffrement TLS (HTTPS) dans vos conteneurs Docker

👋 Bienvenue sur la documentation de Stackhero !

Stackhero propose une solution Docker cloud CaaS (Containers as a Service) prête à l'emploi offrant de nombreux avantages, notamment :

  • Déployez facilement vos containers en production avec un simple docker-compose up.
  • Nom de domaine personnalisable sécurisé avec HTTPS (par exemple, https://api.votre-entreprise.com, https://www.votre-entreprise.com, https://backoffice.votre-entreprise.com).
  • Performance optimale et sécurité robuste grâce à une VM privée et dédiée.
  • Mises à jour simplifiées en un clic.

Gagnez du temps et simplifiez-vous la vie : il suffit de 5 minutes pour essayer la solution d'hébergement cloud Docker CaaS de Stackhero et déployer vos containers en production !

Chaque instance Stackhero pour Docker inclut un serveur Traefik dédié et préconfiguré qui gère le trafic HTTP et le chiffre automatiquement à l'aide de certificats TLS. Cette configuration simplifiée rend le routage simple et efficace. Par exemple :

  • Envoyez le trafic de https://www.my-company.com (avec ou sans le préfixe www) vers votre conteneur frontend.
  • Routez https://www.my-company.com/documentations vers votre conteneur documentations.
  • Dirigez https://api.my-project.io vers votre conteneur api.

Vous pouvez gérer un nombre illimité de domaines avec création et renouvellement automatiques des certificats TLS. Le meilleur, c'est que vous pouvez configurer tout cela en seulement trois lignes !

Dans tous les exemples de configuration suivants, vous devrez remplacer <XXXXXX>.stackhero-network.com par le nom de domaine de votre instance Stackhero pour Docker.

Voici un exemple basique de fichier docker-compose.yml :

services:
  test:
    image: nginx
    labels:
      - "traefik.enable=true" # Activer Traefik pour router le trafic vers ce conteneur
      - "traefik.http.routers.test.rule=Host(`<XXXXXX>.stackhero-network.com`)" # Définir l'hôte
      - "traefik.http.routers.test.tls.certresolver=letsencrypt" # Utiliser 'letsencrypt' comme résolveur de certificat TLS

Dans cet exemple, un conteneur nommé test fonctionne avec l'image Nginx. La configuration clé est fournie dans la section labels. Vous devez simplement copier ces lignes dans votre fichier docker-compose.yml et remplacer <XXXXXX>.stackhero-network.com par votre domaine de service.

Vous pouvez déployer le conteneur en utilisant :

docker context use <XXXXXX>.stackhero-network.com
docker-compose up

Après le démarrage du conteneur, visitez https://<XXXXXX>.stackhero-network.com/ pour voir la page "Welcome to nginx!".

Page d'accueil NginxPage d'accueil Nginx

Si vous ne voyez pas la page d'accueil Nginx, vérifiez le tableau de bord Traefik pour d'éventuelles erreurs !

Avec cette configuration, les requêtes HTTP envoyées à <XXXXXX>.stackhero-network.com sont routées vers votre conteneur test et Traefik crée et gère automatiquement les certificats TLS pour HTTPS.

Dans l'exemple précédent, nous avons utilisé le domaine par défaut <XXXXXX>.stackhero-network.com. En pratique, vous utiliserez probablement vos propres domaines d'entreprise ou de projet, tels que www.my-company.com ou api.my-project.io. La section ci-dessous explique comment configurer des domaines personnalisés.

Dans cet exemple, vous allez configurer le domaine api.my-project.io. Remplacez my-project.io par un domaine que vous possédez et api par votre sous-domaine souhaité.

Tout d'abord, mettez à jour les paramètres DNS de votre domaine pour que api.my-project.io pointe vers votre domaine <XXXXXX>.stackhero-network.com.

  1. Connectez-vous à votre fournisseur de domaine et accédez à votre configuration DNS.
  2. Créez une nouvelle entrée nommée api (ou un autre sous-domaine de votre choix), définissez son type sur CNAME et définissez sa destination sur <XXXXXX>.stackhero-network.com.

Exemple de configuration DNS sur l'interface DNS de CloudflareExemple de configuration DNS sur l'interface DNS de Cloudflare

Une fois le DNS configuré, vous pouvez le valider en exécutant :

host api.my-project.io

Vous devriez voir une réponse similaire à :

api.my-project.io is an alias for <XXXXXX>.stackhero-network.com

La propagation DNS peut prendre jusqu'à 24 heures selon votre fournisseur. Si la commande host ne renvoie pas la réponse attendue, veuillez patienter et réessayer plus tard.

Ensuite, mettez à jour votre fichier docker-compose.yml avec la configuration suivante :

services:
  api:
    image: traefik/whoami
    hostname: api
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.my-project.io`)" # Ajoutez votre domaine ici
      - "traefik.http.services.api.loadbalancer.server.port=<PORT>" # Remplacez "<PORT>" par le port sur lequel votre API écoute
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"

N'oubliez pas de remplacer api.my-project.io par votre domaine réel dans le label Traefik Host.

Déployez votre conteneur avec :

docker-compose up -d

Puis visitez https://api.my-project.io. Vous devriez voir une page texte affichant le nom d'hôte de votre conteneur api.

Preuve que Traefik gère notre trafic HTTP avec chiffrement TLS pour notre nouveau domainePreuve que Traefik gère notre trafic HTTP avec chiffrement TLS pour notre nouveau domaine

Lors de la première création du conteneur, les certificats TLS peuvent prendre quelques secondes à générer. Si vous rencontrez une erreur TLS, attendez quelques secondes et actualisez la page pour laisser le temps aux certificats d'être générés.

Félicitations, vous avez maintenant configuré votre premier domaine personnalisé !

Lors de la définition d'une URL de site web telle que my-company.com, il est judicieux de configurer également un sous-domaine "www". Cela garantit que les utilisateurs qui se connectent via www.my-company.com sont redirigés vers votre site principal et aide à éviter les problèmes de contenu dupliqué.

Dans l'exemple ci-dessous, my-company.com et www.my-company.com sont tous deux gérés. Les utilisateurs accédant à www.my-company.com sont redirigés vers my-company.com :

services:
  frontend:
    image: traefik/whoami
    hostname: frontend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`my-company.com`) || Host(`www.my-company.com`)" # Ajoutez les deux domaines ici
      - "traefik.http.services.frontend.loadbalancer.server.port=<PORT>" # Remplacez "<PORT>" par le port sur lequel votre frontend écoute
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"

      # Rediriger 'www.my-company.com' vers 'my-company.com' :
      - 'traefik.http.routers.frontend.middlewares=redirect-www'
      - "traefik.http.middlewares.redirect-www.redirectregex.regex=^https://www.my-company.com/(.*)"
      - "traefik.http.middlewares.redirect-www.redirectregex.replacement=https://my-company.com/$${1}"
      - "traefik.http.middlewares.redirect-www.redirectregex.permanent=true"

Supposons que vous ayez un conteneur dédié à votre site de documentation. Vous pourriez vouloir router https://my-company.com/docs vers ce conteneur tout en envoyant d'autres requêtes, telles que https://my-company.com/, vers votre conteneur frontend. L'exemple ci-dessous montre comment cela est accompli :

services:
  documentations:
    image: traefik/whoami
    hostname: documentations
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.documentations.rule=Host(`my-company.com`) && PathPrefix(`/docs`)" # Définir le préfixe de chemin ici
      - "traefik.http.services.documentations.loadbalancer.server.port=<PORT>" # Remplacez "<PORT>" par le port sur lequel votre conteneur de documentation écoute
      - "traefik.http.routers.documentations.tls.certresolver=letsencrypt"

  frontend:
    image: traefik/whoami
    hostname: frontend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`my-company.com`) || Host(`www.my-company.com`)"
      - "traefik.http.services.frontend.loadbalancer.server.port=<PORT>" # Remplacez "<PORT>" par le port sur lequel votre frontend écoute
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"

      # Rediriger 'www.my-company.com' vers 'my-company.com' :
      - 'traefik.http.routers.frontend.middlewares=redirect-www'
      - "traefik.http.middlewares.redirect-www.redirectregex.regex=^https://www.my-company.com/(.*)"
      - "traefik.http.middlewares.redirect-www.redirectregex.replacement=https://my-company.com/$${1}"
      - "traefik.http.middlewares.redirect-www.redirectregex.permanent=true"

Maintenant, visiter https://my-company.com/docs (ou tout sous-chemin tel que https://my-company.com/docs/something) affichera le contenu du conteneur documentations. D'autres chemins, par exemple https://my-company.com/help, seront servis par le conteneur frontend.

Par défaut, Traefik se connecte au premier port exposé du conteneur. Dans certains cas, vous pourriez avoir besoin de spécifier un port particulier. L'exemple ci-dessous montre comment définir un port personnalisé :

services:
  frontend:
    image: traefik/whoami
    hostname: frontend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`my-company.com`)"
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"

      # Router le trafic de 'https://my-company.com' vers le conteneur 'frontend' sur le port 80
      - "traefik.http.services.frontend.loadbalancer.server.port=80"

Lors de la définition d'un conteneur dans votre fichier docker-compose.yml, quelques champs sont importants pour une meilleure cohérence et une gestion facilitée. Envisagez d'utiliser la configuration recommandée suivante :

services:
  <CONTAINER_NAME>:
    image: traefik/whoami
    hostname: <CONTAINER_NAME>
    container_name: <CONTAINER_NAME>
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.<CONTAINER_NAME>.rule=Host(`my-company.com`)"
      - "traefik.http.routers.<CONTAINER_NAME>.tls.certresolver=letsencrypt"

Remplacez simplement <CONTAINER_NAME> par le nom souhaité pour votre conteneur, par exemple frontend.

Lors de la création d'un sous-domaine, Let's Encrypt suit les RFC 952 et 1123, qui n'autorisent que les caractères dans l'ensemble [a-zA-Z0-9-].

Bien que les underscores ('_') soient autorisés dans les noms d'enregistrements DNS, ils ne sont pas acceptables dans les noms d'hôte. En conséquence, Let's Encrypt rejette les sous-domaines tels que "my_subdomain.example.com" et affiche l'erreur "Domain name contains an invalid character".

Pour résoudre ce problème, supprimez simplement tous les underscores de vos sous-domaines.