Déploiement d’une application React sur VPS avec Traefik et CI/CD

|

Ce document résume la procédure pour héberger une application React (construite avec Vite) sur un serveur VPS (Ubuntu) déjà équipé de Traefik. Le même socle de VPS avec Docker et Traefik permet aussi d’héberger Supabase en auto-hébergement.

L’architecture finale utilise GitHub Actions pour un workflow CI/CD : le build Docker est effectué par GitHub, et le VPS se contente de télécharger et de redémarrer l’image Docker finale. Le même serveur peut aussi héberger n8n et ses outils d’IA, une fois préparé pour l’auto-hébergement sur VPS avec sudo et un espace d’échange.

Prérequis

  • Un VPS (Ubuntu) avec Docker, Docker Compose et Traefik opérationnel.
  • Un nom de domaine pointant vers l’IP du VPS.
  • Un dépôt GitHub privé pour l’application (votre-organisation/mon-projet-react).
  • Un compte Docker Hub ou GitHub Container Registry (GHCR) pour héberger l’image.

Phase 1 : Fichiers de l’application React

À la racine de votre projet React local, trois fichiers sont nécessaires.

1. .dockerignore

# .dockerignore - Exclude development files from the Docker context
node_modules
dist
.git
.env

2. Dockerfile

Ce fichier utilise un multi-stage build pour créer une image légère contenant Nginx, qui sert les fichiers statiques de React.

# Dockerfile - Build and serve the React application

# Stage 1: Build the React app (using Vite's output dir 'dist')
FROM node:20-alpine AS builder
WORKDIR /app

COPY package.json package-lock.json* ./
RUN npm install --frozen-lockfile

COPY . .
RUN npm run build

# Stage 2: Serve the build with Nginx
FROM nginx:1.27-alpine
WORKDIR /usr/share/nginx/html

# Clean default Nginx content
RUN rm -rf ./*

# Copy built assets from builder stage (Vite outputs to 'dist')
COPY --from=builder /app/dist .

# Expose port 80 (Nginx default)
EXPOSE 80

# Run Nginx
CMD ["nginx", "-g", "daemon off;"]

3. docker-compose.yml

Ce fichier est utilisé par le VPS pour exécuter le conteneur. Notez qu’il n’utilise pas build: . ; il référence directement l’image qui sera construite par la CI/CD.

# docker-compose.yml - Defines the service for production pulling from a registry
services:
  react_app:
    # Pull the image built by GitHub Actions (GHCR)
    image: ghcr.io/votre-organisation/mon-projet-react:latest
    container_name: react_app_prod
    
    # Ensure Docker Compose always pulls the newest 'latest' image
    pull_policy: always
    restart: unless-stopped
    networks:
      # Connect to the existing Traefik network
      - traefik_web
    
    labels:
      # === Traefik Configuration ===
      - "traefik.enable=true"
      
      # --- HTTP Router Definition ---
      - "traefik.http.routers.react-app.rule=Host(`react.votre-domaine.com`)"
      - "traefik.http.routers.react-app.entrypoints=websecure"
      - "traefik.http.routers.react-app.tls.certresolver=mon-resolver-tls"
      
      # --- Service Definition ---
      - "traefik.http.services.react-app.loadbalancer.server.port=80"

networks:
  traefik_web:
    # Connect to the external network managed by Traefik
    external: true

Phase 2 : Configuration des accès (Clés SSH)

Trois clés SSH distinctes sont nécessaires pour sécuriser le flux :

  1. Clé SSH du compte GitHub (Locale)
    • Emplacement : ~/.ssh/id_ed25519 (sur votre machine de développement locale).
    • Usage : Pousser (git push) le code local vers GitHub.
    • Configuration : À ajouter dans GitHub > Settings > SSH and GGPG keys.
  2. Clé de déploiement (VPS)
    • Emplacement : /home/user/.ssh/id_deploy (sur le VPS).
    • Usage : Permettre au VPS de cloner (git clone) le dépôt privé (uniquement pour la configuration initiale).
    • Configuration : Clé publique à ajouter dans Dépôt GitHub > Settings > Deploy keys (lecture seule).
  3. Clé de déploiement (CI/CD)
    • Emplacement : ~/.ssh/id_github_action (générée localement, mais utilisée par l’action).
    • Usage : Permettre à GitHub Actions de se connecter en SSH au VPS pour exécuter les commandes de déploiement.
    • Configuration (Clé privée) : À ajouter dans Dépôt GitHub > Settings > Secrets > Actions (ex: VPS_SSH_PRIVATE_KEY).
    • Configuration (Clé publique) : À ajouter au fichier /home/user/.ssh/authorized_keys sur le VPS.

Phase 3 : Workflow CI/CD (GitHub Actions)

Créez ce fichier à la racine de votre projet pour automatiser le déploiement.

Chemin : .github/workflows/deploy.yml

# .github/workflows/deploy.yml - Workflow to build and deploy the React app

name: Build and Deploy React App

on:
  push:
    # Triggers on push to the 'main' branch
    branches: [ "main" ]
  workflow_dispatch:
    # Allows manual triggering from the GitHub Actions tab

permissions:
  contents: read
  packages: write

jobs:
  build-and-push-image:
    name: Build and Push Docker Image
    runs-on: ubuntu-latest
    
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4

      - name: Log in to GitHub Container Registry (GHCR)
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/votre-organisation/mon-projet-react:latest

  deploy-to-vps:
    name: Deploy to VPS
    runs-on: ubuntu-latest
    needs: build-and-push-image

    steps:
      - name: SSH and Deploy
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USERNAME }}
          key: ${{ secrets.VPS_SSH_PRIVATE_KEY }}
          
          # 'script' runs these commands on the VPS
          script: |
            cd /opt/stacks/mon-projet-react
            docker pull ghcr.io/votre-organisation/mon-projet-react:latest
            docker compose up -d
            docker image prune -f

Secrets GitHub Actions Requis

  • VPS_HOST : L’adresse IP ou le domaine du VPS.
  • VPS_USERNAME : Le nom d’utilisateur pour la connexion SSH (ex: user).
  • VPS_SSH_PRIVATE_KEY : La clé privée de la Clé de déploiement (CI/CD) (voir Phase 2).

Phase 4 : Stratégies de Déploiement

Option A : Déploiement par Branche (Standard)

Cette approche utilise une branche develop pour l’itération et main pour la production.

  1. Itération : Travaillez localement, poussez sur la branche develop.git checkout develop git push origin develop
    Aucun déploiement n’est déclenché.
  2. Production : Lorsque le code est prêt, fusionnez develop dans main.git checkout main git merge develop git push origin main
    Le push sur main déclenche le workflow GitHub Actions et met à jour le site.

Option B : Déploiement Manuel (Adapté aux services tiers)

Si un service tiers (ex: un outil d’itération front-end) force les push sur la branche main, modifiez le workflow (deploy.yml) pour empêcher les déploiements automatiques.

  1. Modifier deploy.yml :Supprimez la section on: push: et ne conservez que on: workflow_dispatch:.
  2. Itération : Le service tiers pousse sur main.Aucun déploiement n’est déclenché.
  3. Production :
    • Allez sur la page du dépôt GitHub > Actions.
    • Sélectionnez le workflow « Build and Deploy React App ».
    • Cliquez sur le bouton Run workflow (Exécuter le workflow).

Publications similaires