Déploiement automatisé de ce portfolio (CI/CD)
Comment ce portfolio est construit avec Astro puis déployé automatiquement via GitLab CI/CD, une image Docker Nginx, Watchtower et Traefik — le tout auto-hébergé.
Introduction
Pour présenter mes projets et compétences, je voulais un site simple à maintenir, facilement modifiable et intégré dans une logique DevOps. Ce portfolio est un site statique généré avec Astro, déployé automatiquement sur mon infrastructure personnelle.
🔗 Dépôt GitLab : gitlab.ggcorp.it/GGauzins/portfolio
Pourquoi GitLab (auto-hébergé) ?
- Self-hosting : GitLab tourne sur mes propres serveurs — contrôle total sur l’infra, la sécurité et les données.
- Simplicité : je clone, je modifie, je
git push. - Automatisation CI/CD : GitLab construit l’image Docker à chaque commit sur
main. - Développement structuré : je développe sur une branche
deven local (npm run dev), et la production (main) n’est mise à jour qu’après validation.
Stratégie de déploiement : Docker + Watchtower
Mon idée de départ était GitLab Pages, mais l’usage d’un domaine personnalisé (www.ggauzins.fr) imposait une 2ᵉ IP publique sur le serveur GitLab — incompatible avec mon infra. J’ai donc opté pour une solution Dockerisée :
- Le site est construit avec Astro via GitLab CI.
- Une image Docker (Nginx) est construite et poussée dans le GitLab Container Registry.
- Une VM sous Docker exécute un conteneur basé sur cette image.
- Watchtower surveille ce conteneur et tire automatiquement la dernière version publiée.
Résultat : je garde la simplicité d’un git push tout en maîtrisant l’hébergement et mon domaine.
Technologies utilisées
- Astro — Générateur de site statique
- Docker — Conteneurisation
- GitLab CI/CD — Build & déploiement
- GitLab Container Registry — Stockage des images
- Watchtower — Mise à jour automatique des conteneurs
- Traefik — Reverse proxy + SSL Let’s Encrypt
- DNS OVH (DNS challenge & wildcard)
Dockerfile (multi-stage)
# --- Étape 1 : build du site avec Node ---
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# --- Étape 2 : runtime léger avec Nginx ---
FROM nginx:1.27-alpine AS runtime
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Pipeline GitLab CI
Seule la branche main déclenche le build et le push de l’image. La VM, via Watchtower, récupère ensuite l’image :latest.
stages:
- build_image
build_image:
stage: build_image
image: docker:latest
services:
- name: docker:dind
alias: docker
variables:
DOCKER_HOST: "tcp://docker:2375"
DOCKER_TLS_CERTDIR: ""
before_script:
- docker login -u gitlab-ci-token -p "$CI_JOB_TOKEN" "$CI_REGISTRY"
script:
- docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" .
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
- docker tag "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" "$CI_REGISTRY_IMAGE:latest"
- docker push "$CI_REGISTRY_IMAGE:latest"
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
Reverse proxy Traefik
http:
routers:
portfolio:
entryPoints: [websecure]
rule: "Host(`www.ggauzins.fr`)"
tls:
certResolver: lets-encr
service: portfolio
redirect-naked:
entryPoints: [websecure]
rule: "Host(`ggauzins.fr`)"
middlewares: [redirect-to-www]
service: noop@internal
tls:
certResolver: lets-encr
middlewares:
redirect-to-www:
redirectRegex:
regex: "^https?://ggauzins\\.fr/(.*)"
replacement: "https://www.ggauzins.fr/$1"
permanent: true
services:
portfolio:
loadBalancer:
servers:
- url: "http://172.16.20.7:8086/"
Cela permet de sécuriser les deux domaines (www. et nu) en HTTPS via Let’s Encrypt, et de rediriger ggauzins.fr vers www.ggauzins.fr.
Docker Compose (VM de prod)
services:
portfolio:
image: registry.ggcorp.it/ggauzins/portfolio:latest
container_name: portfolio
restart: unless-stopped
ports:
- "8086:80"
watchtower:
image: containrrr/watchtower
container_name: watchtower
environment:
- WATCHTOWER_POLL_INTERVAL=300
- WATCHTOWER_CLEANUP=true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: portfolio
Résultat
- Site en ligne avec HTTPS : www.ggauzins.fr
- Déploiement 100 % automatisé : un simple
git pushsurmain - Image Docker toujours à jour grâce à Watchtower
- Domaine personnalisé et infrastructure maîtrisée
Conclusion
Ce projet met en pratique des compétences DevOps complètes : CI/CD, conteneurisation, reverse proxy, gestion de certificats SSL et automatisation du déploiement — appliquées à un site statique moderne sous Astro.