added docker prod files

This commit is contained in:
kinou-p 2025-10-02 16:54:31 +02:00
parent f83a6add48
commit 88a4fddf17
6 changed files with 272 additions and 0 deletions

15
.dockerignore Normal file
View File

@ -0,0 +1,15 @@
node_modules
npm-debug.log
.git
.gitignore
.env
.env.local
.env*.local
dist
README.md
.vscode
.idea
*.md
.DS_Store
*.log
test

31
Dockerfile Normal file
View File

@ -0,0 +1,31 @@
# Étape 1: Build
FROM node:18-alpine AS builder
WORKDIR /app
# Copier les fichiers de dépendances
COPY package*.json ./
# Installer les dépendances
RUN npm ci --only=production
# Copier le code source
COPY . .
# Build l'application en mode production
RUN npm run build
# Étape 2: Production avec Nginx
FROM nginx:alpine
# Copier les fichiers buildés depuis l'étape builder
COPY --from=builder /app/dist /usr/share/nginx/html
# Copier la configuration Nginx optimisée
COPY nginx.conf /etc/nginx/nginx.conf
# Exposer le port 80
EXPOSE 80
# Démarrer Nginx
CMD ["nginx", "-g", "daemon off;"]

29
docker-compose.yml Normal file
View File

@ -0,0 +1,29 @@
services:
portfolio-website:
restart: unless-stopped
build:
context: .
dockerfile: Dockerfile
container_name: portfolio-website
networks:
- portfolio
labels:
- "traefik.enable=true"
# Configuration HTTPS
- "traefik.http.routers.portfolio-website.rule=Host(`alexandre-pommier.com`) || Host(`www.alexandre-pommier.com`)"
- "traefik.http.routers.portfolio-website.entrypoints=websecure"
- "traefik.http.routers.portfolio-website.tls=true"
- "traefik.http.routers.portfolio-website.tls.certresolver=letsencrypt"
- "traefik.http.services.portfolio-website.loadbalancer.server.port=80"
# Redirection HTTP vers HTTPS
- "traefik.http.routers.portfolio-website-http.rule=Host(`alexandre-pommier.com`) || Host(`www.alexandre-pommier.com`)"
- "traefik.http.routers.portfolio-website-http.entrypoints=web"
- "traefik.http.routers.portfolio-website-http.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true"
networks:
portfolio:
external: true

90
nginx.conf Normal file
View File

@ -0,0 +1,90 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# Performance optimizations
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml+rss
application/rss+xml font/truetype font/opentype
application/vnd.ms-fontobject image/svg+xml;
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Cache static assets - Images
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Cache static assets - CSS/JS
location ~* \.(css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Cache static assets - Fonts
location ~* \.(woff|woff2|ttf|otf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Access-Control-Allow-Origin "*";
}
# SPA fallback - toutes les routes vers index.html
location / {
try_files $uri $uri/ /index.html;
}
# Disable cache for index.html
location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# Disable cache for service worker if you add one later
location = /service-worker.js {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# Error pages
error_page 404 /index.html;
}
}

82
test Normal file
View File

@ -0,0 +1,82 @@
Parfait 👌 je vois ton `docker-compose.yml` : là tu fais tourner ton **dev server Vite** dans un conteneur, ce qui explique tes 14s de LCP/FCP.
En prod, il faut **builder une image optimisée**, puis la servir avec **Nginx** (ou Caddy) plutôt quavec `npm run dev`.
---
### ✅ Version corrigée pour la prod
Voici un exemple de `docker-compose.yml` adapté :
```yaml
version: '3.8'
services:
react_app:
restart: unless-stopped
build:
context: .
dockerfile: Dockerfile
container_name: react_app
labels:
- "traefik.enable=true"
- "traefik.http.routers.react_app.rule=Host(`alexandre-pommier.com`)"
- "traefik.http.routers.react_app.entrypoints=https"
- "traefik.http.routers.react_app.tls=true"
- "traefik.http.services.react_app.loadbalancer.server.port=80"
networks:
- react
networks:
react:
external: true
```
Et tu ajoutes un **Dockerfile multi-stage** à la racine de ton projet :
```dockerfile
# Étape build
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install --frozen-lockfile
COPY . .
RUN npm run build
# Étape serve (nginx)
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```
---
### ⚡️ Explication
* **`npm run build`** → génère des fichiers statiques optimisés dans `/app/dist`.
* **Nginx** → sert ces fichiers (beaucoup plus rapide que `vite dev`).
* **Traefik** → envoie le trafic vers ton conteneur (port `80` interne, pas besoin de `8080`).
* Tu peux ajouter un fichier `nginx.conf` custom si tu veux gérer le cache, gzip/brotli, etc.
---
### 🚀 Commandes
1. Construis limage :
```bash
docker compose build
```
2. Lance-la :
```bash
docker compose up -d
```
Ton site sera servi en **mode prod optimisé** avec un LCP/FCP qui devrait tomber à ~12 secondes 🎯
---
👉 Veux-tu que je tajoute aussi un **nginx.conf optimisé** (cache, compression, HTTP/2 push) pour booster encore plus les Core Web Vitals ?

View File

@ -22,4 +22,29 @@ export default defineConfig(({ mode }) => ({
"@": path.resolve(__dirname, "./src"),
},
},
build: {
// Optimisations pour la production
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // Retire les console.log en production
drop_debugger: true,
},
},
// Chunking optimal pour de meilleures performances
rollupOptions: {
output: {
manualChunks: {
'react-vendor': ['react', 'react-dom', 'react-router-dom'],
'ui-vendor': ['framer-motion', 'lucide-react'],
'particles': ['@tsparticles/react', '@tsparticles/slim'],
'radix-ui': Object.keys(require('./package.json').dependencies).filter(key => key.startsWith('@radix-ui')),
},
},
},
// Optimisation des assets
assetsInlineLimit: 4096, // Images < 4kb seront inline en base64
chunkSizeWarningLimit: 1000, // Augmenter la limite d'avertissement
sourcemap: false, // Désactiver les sourcemaps en production
},
}));