Tous les articles

2 min de lecture

Déployer Astro avec Docker et Caddy

Un build statique, deux conteneurs et un certificat TLS automatique — sans dépendre d’une plateforme.

  • Astro
  • Docker
  • Caddy
  • CI/CD

Le problème

Un site Astro produit des fichiers statiques. On pourrait les copier sur un VPS avec scp, mais chaque mise à jour deviendrait une opération manuelle, sans traçabilité ni retour arrière. L’objectif est inverse : une image immuable par commit, un déploiement reproductible et un certificat TLS qui se renouvelle seul.

Un build en deux étapes

Le premier étage installe les dépendances et construit le site. Le second ne contient que nginx et les fichiers générés : l’image finale ne transporte ni Node, ni node_modules.

FROM node:22-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine AS runtime
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist /usr/share/nginx/html

Le point important est le COPY sélectif : package*.json d’abord, le reste ensuite. Tant que les dépendances ne changent pas, Docker réutilise le cache et le build reste rapide.

Caddy plutôt qu’un nginx exposé

Caddy termine le TLS et route le trafic vers les conteneurs internes. Aucun port applicatif n’est publié sur l’hôte : seul Caddy écoute sur 80 et 443.

hosayni.com {
	encode zstd gzip
	root * /srv/web
	try_files {path} {path}/ /404.html
	file_server

	handle /api/* {
		reverse_proxy api:8000
	}

	header {
		Strict-Transport-Security "max-age=31536000; includeSubDomains"
		X-Content-Type-Options "nosniff"
		Referrer-Policy "strict-origin-when-cross-origin"
	}
}

Caddy obtient et renouvelle le certificat sans intervention. La directive try_files reproduit le comportement d’un hébergement statique classique : /fr/projets/ sert index.html, et une URL inconnue tombe sur la page 404.

Ce que ça change

  • Le déploiement devient docker compose pull && docker compose up -d.
  • Un retour arrière consiste à relancer le tag SHA précédent.
  • Les en-têtes de sécurité sont centralisés au même endroit que le TLS.
  • Le site reste servi même si l’API est momentanément indisponible.

Pour aller plus loin

La pièce manquante est l’automatisation : construire les images dans GitHub Actions, les publier sur ghcr.io, puis déclencher le déploiement par SSH avec un healthcheck avant de valider la nouvelle version. C’est exactement le pipeline décrit dans la page Infrastructure de ce site.