Héberger ses propres services managés sur un VPS avec Træfik et Docker / Compose (part. 3)

📚 Cet article fait partie de la série “Héberger ses propres services managés sur un VPS avec Træfik et Docker / Compose”. Voir : part. 1 / part. 2 / part. 3

Table des matières

Procédure

La recette pour déployer et administrer un service Docker via Træfik est un peu toujours la même.

  1. Il faut commencer par étudier rapidement l’architecture de la solution pour comprendre quelles sont les briques principales (webapp, api, db, cache, etc.), celles secondaires, les variations d’installation possibles (utiliser telle ou telle base de données, tel ou tel web server, etc.).
  2. Une fois qu’on est chaud, on commence par déclarer un enregistrement DNS de type CNAME pointant vers l’URL serveur mon-serveur.jbuget.fr. (histoire d’éviter des problèmes de génération de certificats SSL/Let’s Encrypt)
  3. On recherche au sein du projet ou de l’organisation GitHub / GitLab du matériel Docker, l’idéal étant de trouver un fichier docker-compose.yml proposé par l’éditeur et prêt à l’emploi
  4. Sur notre serveur, on crée un répertoire dédié pour y déclarer ou copier-coller le fichier docker-compose.yml correspondant
  5. On renseigne les variables d’environnement dans le fichier Compose ou les éventuels fichiers de config associés
  6. Dans le fichier Compose, dans la partie “définition du service Web exposé”, on ajoute la partie labels
  7. Si la stack comporte plusieurs composants qui doivent communiquer entre eux (cas commun), on prend soin de définir pour chaque composant les bons réseaux Docker (“internal” et/ou “web”)
  8. Si le webserver écoute sur un port autre que 80, on pense à définir le libellé traefik.http.services.<service>.loadbalancer.server.port=<port> et à exposer le port en question
  9. En fin de fichier, on pense à déclarer le/les volumes et les réseaux utilisés, notamment le réseau “web”
  10. Il ne reste plus qu’à démarrer la stack avec la commande docker-compose up -d

Exemple 1 : Plausible

Plausible est une solution open source de suivi de web analytics. C’est une alternative simple et légère à Google Analytics ou Matomo.

💡 Plausible est la solution que j’utilise sur mon site pour suivre et comprendre l’audience, afin de proposer un contenu et une expérience utilisateur pertinente et de qualité. Plus de détails sur la page /stats.

Ce premier exemple est intéressant dans la mesure où la stack nécessaire embarque un composant web (“plausible”) qui écoute sur le port 8000 (plutôt que 80) et nécessite de faire communiquer plusieurs composants sur un réseau interne (lequel n’a pas besoin et ne doit pas être ouvert à l’extérieur).

Comme indiqué dans la documentation officielle, l’installation de Plausible se fait en récupérant les sources du projet.

Dans le répertoire ~/services, créer un nouveau dossier plausible.

# As "toor", from ~/services

$ git clone https://github.com/plausible/hosting plausible && cd plausible

On obtient l’arborescence suivante :

img_1.png

💡 Noter la présence du fichier docker-compose.yml.orig qui est une copie du fichier initial, au cas où…

Éditer le fichier docker-compose.yml comme suit :

version: '3'
services:
  mail:
    image: bytemark/smtp
    restart: always

  plausible_db:
    image: postgres:14.2
    restart: always
    volumes:
      - db:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=postgres
    networks:
      - internal

  plausible_events_db:
    image: yandex/clickhouse-server:21.3.2.5
    restart: always
    volumes:
      - event-data:/var/lib/clickhouse
      - ./clickhouse/clickhouse-config.xml:/etc/clickhouse-server/config.d/logging.xml:ro
      - ./clickhouse/clickhouse-user-config.xml:/etc/clickhouse-server/users.d/logging.xml:ro
    ulimits:
      nofile:
        soft: 262144
        hard: 262144
    networks:
      - internal

  plausible:
    image: plausible/analytics:latest
    restart: always
    command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh db init-admin && /entrypoint.sh run"
    depends_on:
      - plausible_db
      - plausible_events_db
      - mail
    env_file:
      - plausible-conf.env
    networks:
      - internal
      - web
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"
      - "traefik.http.routers.analytics.rule=Host(`plausible.mon-serveur.jbuget.fr`)"
      - "traefik.http.routers.analytics.entrypoints=websecure"
      - "traefik.http.routers.analytics.tls.certresolver=myresolver"
      - "traefik.tcp.routers.analytics.tls.passthrough=true"
      - 'traefik.http.services.analytics.loadbalancer.server.port=8000'

volumes:
  db:
    driver: local
  event-data:
    driver: local
  geoip:
    driver: local

networks:
  internal:
  web:
    external:
      name: web

Éditer le fichier plausible-conf.env comme suit :

# Les valeurs ci-dessous sont évidemment fausses ;-)

ADMIN_USER_EMAIL=admin@jbuget.fr
ADMIN_USER_NAME=replace_me
ADMIN_USER_PWD=replace_me
BASE_URL=https://plausible.mon-serveur.jbuget.fr
SECRET_KEY_BASE=UAVEL...

Relancer l’application :

# As "toor", from ~/services/plausible

$ docker-compose up -d

🎉 L’application est désormais disponible à l’URL https://plausible.mon-serveur.jbuget.fr !

Service Plausible

Shlink est une plateforme Web qui permet de gérer des liens raccourcis. Il s’agit d’une alternative open source à Bitly, TinyURL ou Rebrandly.

2.1. Comprendre le projet

En termes d’architecture, Shlink se présente sous la forme d’une application back-end en PHP et d’un client Web front-end.

Shlink propose une instance en ligne de l’application Web cliente, permettant de se connecter à différents back-end. Dans ces conditions, on peut se contenter de n’installer et gérer que la partie back-end.

⚠️ Remarque : je n’ai pas étudié plus que ça le code du client front-end, et on ne peut pas avoir l’assurance uque c’est bien la version open source qui est déployée sur app.shlink.io. Je vous invite à rester prudent et conscient quant à l’usage de cette dernière.

Shlink propose une image Docker et un fichier docker-compose.yml (factuellement, plusieurs). L’étude du fichier Compose donne à penser que celui-ci n’est pas prêt à l’emploi et qu’il faille creuser un peu, pour sélectionner les briques qui nous siéent, ce qui n’est pas une mince affaire a priori.

Je conseille de suivre la documentation officielle fournie par l’éditeur, pour installer sa propre instance locale via l’image Docker.

L’observation de l’image Docker nous révèle que celle-ci contient tout le nécessaire : l’environnement PHP 8.x, les plugins PHP (PDO, cURL, Intl, etc.), un serveur web openswoole. On voit que l’application supporte plusieurs bases de données, dont PostgreSQL que je préfère personnellement aux autres. On découvre aussi qu’un dossier important est le dossier /etc/shlink dont on sent qu’il faudra le mapper avec un volume local. Enfin, on remarque que le port exposé est le 8080. On se prépare à faire quelque chose pour le prendre en compte.

2.2. Définir une entrée DNS

Comme d’habitude, on se rend sur notre hébergeur de nom de domaine et on ajoute une entrée DNS de type CNAME, depuis l.mon-serveur.jbuuget.fr vers notre routeur mon-serveur.jbuget.fr.

2.3. Générer une clé GeoLite2

Pour pouvoir fournir des métriques d’usage un minimum précises, Shlink permet d’utiliser une base de géolocalisation GeoLite2. Il faut, pour cela, disposer d’une clé d’API GeoLite2.

La procédure consiste à :

  1. se créer un compte MaxMind (gratuit)
  2. générer la clé d’API (gratuit)

Une fois le sésame en poche, il faudra la renseigner dans les arguments d’environnement.

2.4. Créer et éditer les fichiers Docker Compose et de configuration

Comme pour Plausible, tout le nécessaire pour gérer notre instance de back-end Shlink sera géré dans un répertoire dédié : ~/services/shlink.

Listing des fichiers de configuration du service Shlink

Avec tous ces éléments en tête, on peut obtenir le fichier docker-compose.yml suivant :

# ~/services/shlink/docker-compose.yml

version: '3'

services:
  db:
    image: postgres:14.2
    restart: always
    volumes:
      - db:/var/lib/postgresql/data
    env_file:
      - ./shlink-conf.env
    networks:
      - default

  app:
    image: shlinkio/shlink:3.0.3
    restart: always
    links:
      - db
    depends_on:
      - db
    volumes:
      - shlink:/etc/shlink
    env_file:
      - shlink-conf.env
    networks:
      - default
      - web
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"
      - "traefik.http.routers.l.rule=Host(`l.mon-serveur.jbuget.fr`)"
      - "traefik.http.routers.l.entrypoints=websecure"
      - "traefik.http.routers.l.tls.certresolver=myresolver"
      - "traefik.tcp.routers.l.tls.passthrough=true"
      - "traefik.http.services.l.loadbalancer.server.port=8080"

volumes:
  db:
  shlink:

networks:
  default:
  web:
    external:
      name: web
# ~/services/shlink/shlink-conf.env

# Postgres
POSTGRES_USER=postmaster
POSTGRES_PASSWORD=postgres
POSTGRES_DB=shlink

# Shlink
DB_DRIVER=postgres
DB_NAME=${POSTGRES_DB}
DB_USER=${POSTGRES_USER}
DB_PASSWORD=${POSTGRES_PASSWORD}
DB_HOST=db
DB_PORT=5432
DEFAULT_DOMAIN=l.mon-serveur.jbuget.fr
IS_HTTPS_ENABLED=true
GEOLITE_LICENSE_KEY=cbn...

Ce qui est intéressant à mon sens ici est de voir qu’on peut utiliser un même fichier de configuration pour 2 services. Cela dit, ce n’est pas forcément le plus conseillé 😅.

Par ailleurs, je montre ici qu’il est possible et comment appeler une variable d’environnement pour alimenter une autre via la notation ${xxx}.

C’est parti pour générer notre instance de Shlink !

# As "toor", from ~/services/shlink

$ docker-compose up -d

Si tout s’est bien passé, quand vous accédez à votre service - https://l.mon-serveur.jbuget.fr - vous devriez voir cette page d’erreur (eh oui ! encore une page d’erreur qui est un bon signe #LesJoiesDuBack 🙃) :

img_1.png

Un prérequis indispensable à cette étape est la création d’une clé d’API pour accéder à notre back-end Shlink.

La façon la plus rapide et simple que j’ai trouvé, consiste à utiliser le CLI Shlink embarqué dans l’image Docker que l’on utilise.

# As "toor", from ~/services/shlink

$ docker-compose exec app shlink api-key:generate

img_1.png

Conserver bien précieusement la clé obtenue avant de passer à la suite.

Allez sur https://app.shlink.io et déclarez un nouveau serveur :

service_shlink_screenshot.png

Conclusion

On arrive - enfin ! - au bout de cette série.

Pour récapituler, nous avons :

  • commandé, provisionné et sécurisé un serveur IaaS
  • attaché celui-ci à notre sous-DNS de routage mon-serveur.jbuget.fr
  • installé Docker et Docker Compose
  • déclaré et démarré une instance de Træfik (via Docker & Compose)
  • configuré Træfik pour qu’il auto-découvre des services managés via Docker & Compose
  • défini et lancé divers services managés (Whoami, Plausible, Shlink) en suivant la recette (en n’oubliant surtout pas le petit enregistrement DNS/CNAME qui va bien)

Pour aller plus loin, il faudrait :

Liens

Tous les articles de la série

comments powered by Disqus