(Cet article a été généré par DeepSeek V4 Pro, basé sur une session de travail avec MiMo 2.5)
🧪 Le problème
Ce site est un site statique généré avec Eleventy (11ty). Le workflow de base : Markdown en entrée, npm run build pour produire le HTML, rsync via SSH pour publier. Le tout dépend de versions précises de Node, de dépendances locales et d’une clé SSH.
Le problème surgit dès que tu changes de machine : il faut réinstaller Node, relancer npm ci, refaire la chaîne d’outils. Je parlais déjà de Docker pour l’autohébergement, mais Docker peut aussi contenir ton environnement de développement.
🧪 La solution : un devcontainer
Au lieu de documenter les étapes d’installation, je décris l’environnement dans deux fichiers, versionnés dans Git. Docker devient la seule exigence.
Deux fichiers dans .devcontainer/ :
Dockerfile: image Node +rsync+openssh-client;devcontainer.json: configuration pour ton éditeur.
🧪 Le Dockerfile
FROM node:24-bookworm
RUN apt-get update && apt-get install -y --no-install-recommends \
rsync \
openssh-client \
&& rm -rf /var/lib/apt/lists/*
rsync et openssh-client servent au déploiement, pas au build. Le conteneur couvre tout le cycle : construire, servir, publier.
🧪 Le devcontainer.json
{
"name": "site-grav",
"build": { "dockerfile": "Dockerfile" },
"postCreateCommand": "npm ci",
"forwardPorts": [8080],
"mounts": [
"source=${localEnv:HOME}/.ssh,target=/root/.ssh,type=bind,readonly"
],
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ritwickdey.LiveServer"
]
}
}
}
Les points importants :
postCreateCommand:npm cis’exécute automatiquement à la création du conteneur.forwardPorts: le port 8080 est redirigé vers la machine hôte.- Le montage SSH :
~/.sshest monté en lecture seule dans le conteneur, ce qui permet de déployer sans copier la clé privée dans l’image.
🧪 Build et serve
npm ci
npm run build
npm run serve:static
La chaîne de build (Sass, vérification des images, visuels sociaux, optimisation, Eleventy, purge CSS, Pagefind) produit environ 1800 fichiers en une dizaine de secondes. Le site est servi sur http://localhost:8080. Rien ne touche le système hôte.
🧪 Déploiement
Le déploiement repose sur rsync via SSH, comme décrit dans l’article sur le déploiement avec un wrapper sudo restreint. rsync et openssh-client étant dans l’image, et la clé SSH montée, deploy.sh fonctionne directement depuis le conteneur. Les variables DEPLOY_USER, DEPLOY_HOST, DEPLOY_PATH et DEPLOY_KEY restent à fournir.
En dehors d’un éditeur, un docker run reproduit le tout :
docker run -it --rm \
-v "$(pwd)":/workspaces/site-grav \
-w /workspaces/site-grav \
-v "$HOME/.ssh":/root/.ssh:ro \
-e DEPLOY_USER="$DEPLOY_USER" \
-e DEPLOY_HOST="$DEPLOY_HOST" \
-e DEPLOY_PATH="$DEPLOY_PATH" \
-e DEPLOY_KEY=/root/.ssh/id_deploy \
-p 8080:8080 \
site-grav npm run deploy
🧪 Limites
Le montage SSH suppose que la clé est sur la machine hôte. Et Docker Desktop a un coût en RAM, disque et abstraction. Pour un usage solo minimaliste, un simple nvm suffit. Le devcontainer devient pertinent dès que tu partages l’environnement.
🧪 Conclusion
Décris l’environnement dans deux fichiers, versionne-les, et Docker devient la seule exigence. Construire, servir et déployer un site 11ty se réduit alors à un git clone suivi d’un « reopen in container ».
Comment construire et déployer un site 11ty sur n’importe quelle machine avec une seule exigence ?
Décris ton environnement dans un .devcontainer (une image Node avec rsync et openssh-client, plus une config qui monte ta clé SSH et installe les dépendances). Docker devient la seule dépendance : le site se construit, se sert et se déploie depuis le conteneur de façon reproductible.