Infrastructure

Déployer un blog Jekyll en production avec Docker et HAProxy

Déployer un site Jekyll en production avec son propre serveur WEBrick dans un conteneur Docker, reverse-proxifié par HAProxy — sans étape de build séparée.

Table des matières

Un blog Jekyll classique se déploie généralement en générant du HTML statique (jekyll build) servi ensuite par nginx ou Apache. Cette approche est la plus performante, mais elle impose un cycle build → copie des fichiers → redéploiement à chaque modification. Pour un blog personnel à faible trafic, ce guide propose une alternative volontairement plus simple : faire tourner le serveur jekyll serve (WEBrick) directement en conteneur, avec les sources montées en volume, reverse-proxifié par HAProxy.

Pourquoi pas un build statique classique ?

Un pipeline build + nginx est plus rapide à servir, mais chaque modification de contenu impose de reconstruire l’image ou de resynchroniser un dossier de sortie. Pour un site de quelques articles, non critique, on peut accepter un serveur un peu moins rapide en échange d’une simplicité totale : modifier un fichier sur le disque suffit, Jekyll régénère le site tout seul.

Dockerfile

Deux stages : base installe les dépendances Ruby, dev lance le serveur. Ce même stage sert aussi bien en développement local qu’en “production” — seule la commande de lancement change entre les deux docker-compose.yml.

FROM ruby:3.3-alpine AS base

RUN apk add --no-cache \
      build-base git nodejs npm tzdata \
      libffi-dev yaml-dev zlib-dev \
      ca-certificates

WORKDIR /site
COPY Gemfile Gemfile.lock ./
RUN bundle install --jobs 4 --retry 3

FROM base AS dev
WORKDIR /site
EXPOSE 4000 35729
CMD ["bundle", "exec", "jekyll", "serve", \
     "--host", "0.0.0.0", \
     "--port", "4000", \
     "--livereload", \
     "--future", \
     "--drafts"]
ca-certificates

Sur Alpine, le paquet ca-certificates n’est pas installé par défaut. Sans lui, tout appel HTTPS sortant depuis un plugin Jekyll (Net::HTTP, API externe…) échoue avec une erreur SSL.

docker-compose.public.yml — la version « production »

services:
  jekyll-public:
    build:
      context: .
      target: dev
    container_name: infops-public
    volumes:
      - .:/site
      - gem_cache:/usr/local/bundle
    command: >
      bundle exec jekyll serve
      --host 0.0.0.0
      --port 4000
    ports:
      - "4000:4000"
    environment:
      - JEKYLL_ENV=production
      - TZ=Europe/Paris
    restart: unless-stopped

volumes:
  gem_cache:

Deux différences avec le compose de développement : pas de --drafts/--future (on ne publie que les articles réellement datés et publiés), et JEKYLL_ENV=production pour activer les blocs conditionnels ({% if jekyll.environment == "production" %}) comme le chargement des scripts d’analytics.

--incremental à éviter

Le flag –incremental de Jekyll a un bug connu : il ne recharge pas toujours correctement les layouts/includes modifiés. Sur un site qui tourne en continu avec du contenu qui change souvent, mieux vaut laisser Jekyll régénérer intégralement à chaque changement détecté.

Reverse proxy HAProxy

HAProxy termine le TLS et route le trafic vers le conteneur WEBrick en HTTP simple :

frontend https_front
    bind *:443 ssl crt /etc/haproxy/combined.pem alpn h2,http/1.1

    acl is_main_domain hdr(host) -i 50bvd.com
    use_backend main_website if is_main_domain

backend main_website
    option http-server-close
    option forwardfor
    option httpchk GET /
    http-request set-header X-Forwarded-Port %[dst_port]
    http-request add-header X-Forwarded-Proto https if { ssl_fc }
    timeout tunnel 1h
    server webserver 192.168.1.12:4000 check

Lancer et vérifier

docker compose -f docker-compose.public.yml up -d --build

# Depuis srv-docker
curl -sI http://localhost:4000/
# → HTTP/1.1 200 OK, Server: WEBrick/1.9.2

# Depuis l'extérieur, via HAProxy
curl -sI https://50bvd.com/

Toute modification sur le disque (article, layout, style) est reprise automatiquement en quelques secondes — pas de build ni de redéploiement séparé à orchestrer.

Résultat

  • Site en ligne derrière TLS via HAProxy, sans étape de build manuelle.
  • Modification d’un fichier = site à jour en quelques secondes.
  • Compromis assumé : un peu moins rapide qu’un site statique nginx, largement suffisant pour un blog personnel à faible trafic.

Comments