Déploiement automatique avec GitLab CI - 01 - L'architecture : VPS, Docker Compose et Caddy

L'architecture d'un déploiement automatise : VPS, Docker Compose, Caddy reverse proxy et multi-subdomains avec auto-SSL.

01 - L'architecture : VPS, Docker Compose et Caddy

Ce que tu vas apprendre

  • L'architecture complète d'un déploiement Docker Compose en production
  • Comment Caddy gere le reverse proxy et l'auto-SSL
  • La structure du docker-compose.yml et du Caddyfile
  • Pourquoi Caddy plutot que Nginx ou Traefik

Prerequisites


Vue d'ensemble

Voici l'architecture du projet qui tourne sur paltemps.fr. Un VPS OVH sous Ubuntu 25.04, avec Docker Compose qui orchestre 4 conteneurs :

                        Internet
                           |
                      [ VPS OVH ]
                     Ubuntu 25.04
                           |
                    [ Docker Compose ]
                     /    |    \       \
                    /     |     \       \
              [ Caddy ] [ App ] [ Mail ] [ Chrome ]
              :80/:443  :3000   :25/:587  :9222
                 |
          Reverse Proxy
          Auto-SSL (Let's Encrypt)
                 |
     +-----------+-----------+-----------+
     |           |           |           |
 paltemps.fr  blog.      deck.      benchmark.
              paltemps.fr paltemps.fr paltemps.fr

Caddy est le point d'entree. Il recoit toutes les requêtes HTTP/HTTPS, regarde le header Host, et redirige vers le bon service. L'app Bun gere l'API et sert le frontend. Le serveur mail (docker-mailserver) gere les emails du domaine. Chrome headless fait du scraping de pages web.

Le docker-compose.yml

Voici la structure réelle (simplifiee pour la lisibilité) :

yamlservices:
  app:
    build: .
    restart: unless-stopped
    environment:
      - NODE_ENV=production
      - PORT=3000
    volumes:
      - ./data:/app/data

  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config

  mailserver:
    image: ghcr.io/docker-mailserver/docker-mailserver:latest
    restart: unless-stopped
    hostname: inbox.paltemps.fr
    ports:
      - "25:25"
      - "587:587"
      - "993:993"
    volumes:
      - ./docker-data/dms/mail-data:/var/mail
      - ./docker-data/dms/config:/tmp/docker-mailserver

  chrome:
    image: ghcr.io/browserless/chromium
    restart: unless-stopped
    environment:
      - MAX_CONCURRENT_SESSIONS=2

volumes:
  caddy_data:
  caddy_config:

Chaque service a restart: unless-stopped. Si le VPS reboot, tout redemarre automatiquement. Le volume caddy_data persiste les certificats SSL entre les redemarrages, sinon tu te fais rate-limit par Let's Encrypt.

Le Caddyfile

C'est la que la magie opéré. Caddy fait le reverse proxy ET gere les certificats SSL automatiquement :

paltemps.fr {
    reverse_proxy app:3000
}

blog.paltemps.fr {
    reverse_proxy app:3000
}

deck.paltemps.fr {
    reverse_proxy app:3000
}

benchmark.paltemps.fr {
    reverse_proxy app:3000
}

inbox.paltemps.fr {
    reverse_proxy app:3000
}

C'est tout. Pas de blocs server, pas de listen 443 ssl, pas de ssl_certificate. Tu mets le nom de domaine, Caddy obtient un certificat Let's Encrypt, configure HTTPS, redirige HTTP vers HTTPS. Automatiquement. Au premier démarrage, ca prend environ 30 secondes pour provisionner tous les certificats.

Le Dockerfile (multi-stage)

L'application utilise un Dockerfile multi-stage pour garder l'image legere :

dockerfileFROM oven/bun:1 AS base
WORKDIR /app

FROM base AS install
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile --production

FROM base AS build
COPY --from=install /app/node_modules ./node_modules
COPY . .
RUN bun run build

FROM base AS release
COPY --from=install /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY --from=build /app/public ./public
COPY package.json .

USER bun
EXPOSE 3000
CMD ["bun", "run", "dist/index.js"]

Quatre étapes : base, install des dépendances, build du frontend, image finale. L'image de production ne contient que le strict nécessaire : les node_modules de prod, le code compile et les assets statiques. Pas de devDependencies, pas de sources TypeScript.

Pourquoi Caddy et pas Nginx

J'ai une opinion assez tranchee la-dessus : pour 90% des projets web, Caddy est un meilleur choix que Nginx.

Avec Nginx, tu dois configurer les certificats SSL toi-meme. En général, tu installes Certbot, tu configures un cron pour le renouvellement, tu ecris un bloc server avec les chemins vers les certificats. Ca marche, mais c'est 30 lignes de config en plus et un point de failure supplementaire.

Avec Caddy, tu ecris le nom de domaine. C'est fini. HTTPS est actif. Le certificat se renouvelle tout seul. Zero config supplementaire.

Et Traefik ? Traefik est plus puissant que Caddy, avec une découverte automatique des services Docker via des labels. Mais cette puissance a un coût : la configuration est plus verbeuse, la courbe d'apprentissage est plus raide, et pour un projet avec 4 ou 5 services, c'est clairement overkill. J'ai utilise Traefik sur des projets plus gros et il fait bien son travail, mais ici Caddy gagne par sa simplicité.

Les DNS

Pour que tout fonctionne, il faut que tes enregistrements DNS pointent vers l'IP de ton VPS. Dans le panel OVH (ou ton registrar), tu ajoutes :

paltemps.fr          A    203.0.113.42
blog.paltemps.fr     A    203.0.113.42
deck.paltemps.fr     A    203.0.113.42
inbox.paltemps.fr    A    203.0.113.42
benchmark.paltemps.fr A   203.0.113.42

Ou plus malin, un wildcard :

*.paltemps.fr        A    203.0.113.42

Comme ca, chaque nouveau sous-domaine est automatiquement redirige vers ton VPS. Tu n'ajoutes que l'entree dans le Caddyfile.

La suite

L'architecture est en place. Dans le prochain article, on installe GitLab Runner sur le VPS pour que tout ca se deploie automatiquement a chaque push.


Navigation : Precedent : 00 - Introduction | Suivant : 02 - Installer GitLab Runner


Sources

Retrouve d'autres articles techniques sur paltemps.fr.

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.