La plupart de nos sites hébergés sont rendus statiquement, construits avec des outils comme Hugo, Zola ou Jekyll. En général, tous ces générateurs de site prennent en entrée un format simplifié (généralement Markdown) et génèrent du HTML bien défini en sortie. Reste alors la question : comment puis-je héberger un tel site ?
Il existe des fournisseurs spécialisés proposant de l’hébergement pour sites statiques, mais comme vous le savez, nous avons suivi une voie différente lors de la construction de notre infrastructure principale. Pour notre cloud, le dénominateur commun pour le déploiement est un conteneur. Et avec cela vient la question : comment passer d’une build de site statique à un conteneur qui héberge le site web ?
Commençons donc de zéro en générant une page très simple “hello world” avec Hugo.
hugo new site hello
cd hello
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
echo "theme = 'ananke'" >> hugo.toml
Pour vérifier la build, nous pouvons démarrer le serveur localement :
hugo serve
Puis notre propre page “Hello World” apparaît à l’adresse http://localhost:1313
Jusque-là tout va bien. Maintenant, envisageons de mettre cela dans un conteneur.
Techniquement, nous pouvons emprunter deux chemins différents ici :
Pour rendre notre exemple plus reproductible et moins dépendant des environnements locaux, nous choisissons l’option 1 pour ce scénario. Cela rend également les pipelines CI/CD plus propres puisque l’environnement de build est entièrement défini dans le Dockerfile.
Une image de conteneur commence toujours par une image de base. Pour cela, nous utilisons Alpine Linux car elle est légère (environ 5Mo) et fournit assez d’outils pour notre projet.
Nous utiliserons un build multi-étapes, une technique supportée par les outils modernes de construction d’images qui nous permet d’utiliser une image pour la construction et une autre pour l’exécution. Cela garde notre image finale petite en excluant les outils de build dont nous n’avons pas besoin à l’exécution.
Stage 1: Build
FROM alpine AS build
RUN apk add --no-cache hugo
WORKDIR /src
ADD . .
RUN hugo --minify
Dans cette étape, nous :
--minify pour produire une sortie optimiséeLe site généré se retrouve dans /src/public/.
Stage 2: Runtime
FROM alpine AS runner
RUN apk add --no-cache lighttpd
COPY --from=build /src/public /var/www/localhost/htdocs
EXPOSE 80
CMD ["lighttpd", "-D", "-f", "/etc/lighttpd/lighttpd.conf"]
Dans cette étape, nous :
-D)Voici le Dockerfile complet combinant les deux étapes :
# Stage 1: Build the static site
FROM alpine AS build
RUN apk add --no-cache hugo
WORKDIR /src
ADD . .
RUN hugo --minify
# Stage 2: Serve with lighttpd
FROM alpine AS runner
RUN apk add --no-cache lighttpd
COPY --from=build /src/public /var/www/localhost/htdocs
EXPOSE 80
CMD ["lighttpd", "-D", "-f", "/etc/lighttpd/lighttpd.conf"]
Enregistrez ceci en tant que Dockerfile à la racine de votre projet Hugo.
Vous pouvez utiliser n’importe quel outil de conteneur compatible OCI comme Podman ou Docker. Les exemples ci-dessous utilisent docker, mais podman fonctionne comme un remplaçant direct.
Pour construire l’image :
docker build -t my-website .
Pour l’exécuter localement :
docker run -p 8080:80 --rm my-website
Votre site est maintenant disponible à l’adresse http://localhost:8080
Le flag -p 8080:80 mappe le port 8080 de votre machine au port 80 à l’intérieur du conteneur. Le flag --rm supprime automatiquement le conteneur lorsqu’il s’arrête.
Cette configuration présente plusieurs avantages :
Taille d’image réduite : L’image finale contient uniquement Alpine (~5Mo) + lighttpd (~1Mo) + vos fichiers HTML. Pas de Node.js, pas de Ruby, pas d’outils de build alourdissant votre image de production.
Builds reproductibles : La même version exacte de Hugo s’exécute en CI comme en local, éliminant les problèmes du type “ça marche sur ma machine”.
Démarrage rapide : lighttpd démarre en quelques millisecondes, ce qui rend cette solution parfaite pour les déploiements scale-to-zero sur DTZ.
Sécurité : Le conteneur de production a une surface d’attaque minimale — juste un serveur de fichiers statiques sans runtime dynamique.
Si vous construisez votre image sur un Mac Apple Silicon (ARM64) ou une autre architecture non standard, rappelez-vous que les serveurs tournent généralement sur AMD64 (x86_64). Pour vous assurer que votre conteneur s’exécute correctement sur DTZ (et la plupart des autres fournisseurs cloud), vous devriez spécifier explicitement la plateforme cible lors de la build.
Changez votre commande de build pour :
docker build --platform linux/amd64 -t my-website .
Cela indique à Docker de cross-compiler l’image pour les serveurs Linux standards, garantissant la compatibilité quel que soit la machine sur laquelle vous construisez.
Une fois votre image construite, vous pouvez la pousser vers un registre de conteneurs et la déployer sur DTZ. Si vous utilisez notre registre de conteneurs :
# Tag for DTZ registry
docker tag my-website YOUR_CONTEXT_ID.cr.dtz.dev/my-website:latest
# Login and push
docker login YOUR_CONTEXT_ID.cr.dtz.dev -u apikey
docker push YOUR_CONTEXT_ID.cr.dtz.dev/my-website:latest
Créez ensuite un service de conteneur dans le tableau de bord DTZ pointant vers votre image. Le service gérera automatiquement les certificats TLS, la mise à l’échelle et le routage.
Pour des déploiements automatisés à chaque commit, consultez notre GitHub Action for seamless deployments.
Le même schéma fonctionne pour d’autres générateurs. Voici les changements clés :
For Zola:
FROM alpine AS build
RUN apk add --no-cache zola
WORKDIR /src
ADD . .
RUN zola build
For Jekyll:
FROM ruby:alpine AS build
RUN apk add --no-cache build-base
RUN gem install bundler jekyll
WORKDIR /src
ADD . .
RUN bundle install
RUN bundle exec jekyll build
L’étape runtime reste la même — il suffit de copier depuis /src/public (Zola) ou /src/_site (Jekyll) vers la racine de documents de lighttpd.
Containeriser des sites statiques est simple une fois que vous comprenez le schéma : construire dans une étape, servir depuis une autre. Le résultat est un conteneur minuscule, rapide et sécurisé, parfait pour les déploiements cloud modernes.
Cette approche s’aligne bien avec notre philosophie chez DTZ — utilisation minimale des ressources, démarrages à froid rapides et infrastructure qui se met à l’échelle jusqu’à zéro lorsqu’elle n’est pas utilisée. Un site statique dans un conteneur d’environ 10Mo qui démarre instantanément est à peu près aussi efficace que peut l’être l’hébergement web.