Docker Deployment
Containerisation et déploiement avec Docker
Déployer une application React avec Docker
Docker révolutionne la façon dont nous déployons les applications en permettant de créer des conteneurs légers et portables. Dans ce tutoriel, nous allons apprendre à containeriser une application React et la déployer efficacement.
Introduction à Docker
Qu’est-ce que Docker ?
Docker est une plateforme de containerisation qui permet d’empaqueter une application et ses dépendances dans un conteneur léger et portable. Cela garantit que l’application fonctionne de manière identique sur tous les environnements.
Avantages de Docker pour React
- Cohérence : L’application fonctionne identiquement partout
- Isolation : Chaque conteneur est isolé des autres
- Scalabilité : Facilite la montée en charge
- Déploiement : Processus de déploiement simplifié
- Versioning : Gestion des versions facilitée
Installation de Docker
Sur Windows
- Téléchargez Docker Desktop depuis le site officiel
- Installez et redémarrez votre machine
- Vérifiez l’installation :
docker --version
docker-compose --version
Sur macOS
# Avec Homebrew
brew install --cask docker
# Ou téléchargez Docker Desktop
Sur Linux (Ubuntu)
# Mise à jour des paquets
sudo apt update
# Installation des dépendances
sudo apt install apt-transport-https ca-certificates curl software-properties-common
# Ajout de la clé GPG Docker
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# Ajout du repository Docker
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
# Installation de Docker
sudo apt update
sudo apt install docker-ce
# Vérification
sudo systemctl status docker
Création d’une application React
Initialisation du projet
npx create-react-app react-docker-app
cd react-docker-app
Structure du projet
react-docker-app/
├── public/
├── src/
├── package.json
├── Dockerfile
├── .dockerignore
└── docker-compose.yml
Configuration Docker
Création du Dockerfile
Créez un fichier Dockerfile
à la racine du projet :
# Étape 1: Build de l'application
FROM node:18-alpine as build
# Définir le répertoire de travail
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 de l'application
RUN npm run build
# Étape 2: Servir l'application avec Nginx
FROM nginx:alpine
# Copier les fichiers buildés vers Nginx
COPY --from=build /app/build /usr/share/nginx/html
# Copier la configuration Nginx personnalisée
COPY nginx.conf /etc/nginx/nginx.conf
# Exposer le port 80
EXPOSE 80
# Commande par défaut
CMD ["nginx", "-g", "daemon off;"]
Configuration Nginx
Créez un fichier nginx.conf
:
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# Configuration pour les applications React (SPA)
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Gestion des routes React Router
location / {
try_files $uri $uri/ /index.html;
}
# Cache pour les assets statiques
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Sécurité
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
}
}
Fichier .dockerignore
Créez un fichier .dockerignore
:
node_modules
npm-debug.log
build
.dockerignore
Dockerfile
Dockerfile.prod
.git
.gitignore
README.md
.env
.nyc_output
coverage
.nyc_output
.coverage
.coverage/
Build et exécution
Construction de l’image Docker
# Build de l'image
docker build -t react-docker-app .
# Vérifier que l'image a été créée
docker images
Exécution du conteneur
# Lancer le conteneur
docker run -d -p 3000:80 --name react-app react-docker-app
# Vérifier que le conteneur fonctionne
docker ps
# Voir les logs
docker logs react-app
# Arrêter le conteneur
docker stop react-app
# Supprimer le conteneur
docker rm react-app
Docker Compose
Configuration docker-compose.yml
Créez un fichier docker-compose.yml
:
version: '3.8'
services:
react-app:
build: .
ports:
- "3000:80"
environment:
- NODE_ENV=production
restart: unless-stopped
# Service optionnel : Base de données
database:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
# Service optionnel : Redis pour le cache
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
postgres_data:
Utilisation de Docker Compose
# Lancer tous les services
docker-compose up -d
# Voir les logs
docker-compose logs -f
# Arrêter tous les services
docker-compose down
# Rebuild et relancer
docker-compose up --build -d
Optimisations avancées
Dockerfile multi-stage optimisé
# Étape 1: Build
FROM node:18-alpine as dependencies
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
FROM node:18-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Étape 2: Production
FROM nginx:alpine as production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# Copier les fichiers buildés
COPY --from=build --chown=nextjs:nodejs /app/build /usr/share/nginx/html
# Configuration Nginx
COPY nginx.conf /etc/nginx/nginx.conf
# Sécurité
RUN chown -R nextjs:nodejs /usr/share/nginx/html
USER nextjs
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Variables d’environnement
# Dans le Dockerfile
ARG REACT_APP_API_URL
ARG REACT_APP_VERSION
ENV REACT_APP_API_URL=$REACT_APP_API_URL
ENV REACT_APP_VERSION=$REACT_APP_VERSION
# Build avec des variables
docker build --build-arg REACT_APP_API_URL=https://api.production.com -t react-app .
Fichier .env pour Docker Compose
Créez un fichier .env
:
# Application
REACT_APP_API_URL=https://api.example.com
REACT_APP_VERSION=1.0.0
# Base de données
POSTGRES_DB=myapp
POSTGRES_USER=user
POSTGRES_PASSWORD=securepassword
# Ports
APP_PORT=3000
DB_PORT=5432
Déploiement en production
Avec Docker Swarm
# Initialiser Swarm
docker swarm init
# Déployer la stack
docker stack deploy -c docker-compose.yml react-stack
# Voir les services
docker service ls
# Scaler le service
docker service scale react-stack_react-app=3
Avec Kubernetes
Créez un fichier k8s-deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: react-app
spec:
replicas: 3
selector:
matchLabels:
app: react-app
template:
metadata:
labels:
app: react-app
spec:
containers:
- name: react-app
image: react-docker-app:latest
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: react-app-service
spec:
selector:
app: react-app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
# Déployer sur Kubernetes
kubectl apply -f k8s-deployment.yaml
# Voir les pods
kubectl get pods
# Voir les services
kubectl get services
Monitoring et logs
Configuration des logs
# Dans le Dockerfile
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
Health checks
# Ajout d'un health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
Monitoring avec Docker Compose
version: '3.8'
services:
react-app:
build: .
ports:
- "3000:80"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/"]
interval: 30s
timeout: 10s
retries: 3
# Monitoring
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana
ports:
- "3001:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
Sécurité
Bonnes pratiques de sécurité
# Utiliser des images officielles
FROM node:18-alpine
# Créer un utilisateur non-root
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# Mettre à jour les paquets
RUN apk update && apk upgrade
# Utiliser l'utilisateur non-root
USER nextjs
# Scanner les vulnérabilités
RUN npm audit fix
Configuration Nginx sécurisée
# Masquer la version Nginx
server_tokens off;
# Headers de sécurité
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 "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;
# Limiter la taille des uploads
client_max_body_size 10M;
# Timeout
client_body_timeout 12;
client_header_timeout 12;
keepalive_timeout 15;
send_timeout 10;
CI/CD avec Docker
GitHub Actions
Créez .github/workflows/docker.yml
:
name: Docker Build and Deploy
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: |
myusername/react-app:latest
myusername/react-app:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
GitLab CI
Créez .gitlab-ci.yml
:
stages:
- build
- test
- deploy
variables:
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker build -t $DOCKER_IMAGE .
- docker push $DOCKER_IMAGE
deploy:
stage: deploy
image: alpine:latest
script:
- apk add --no-cache curl
- curl -X POST $WEBHOOK_URL
only:
- main
Troubleshooting
Problèmes courants
- Erreur de permissions :
# Changer les permissions
sudo chown -R $USER:$USER /path/to/project
- Port déjà utilisé :
# Trouver le processus utilisant le port
sudo lsof -i :3000
# Tuer le processus
sudo kill -9 PID
- Problème de cache :
# Nettoyer le cache Docker
docker system prune -a
- Erreur de build :
# Build sans cache
docker build --no-cache -t react-app .
Debugging
# Entrer dans le conteneur
docker exec -it react-app sh
# Voir les logs en temps réel
docker logs -f react-app
# Inspecter le conteneur
docker inspect react-app
Conclusion
Docker transforme la façon dont nous déployons les applications React en offrant :
- Cohérence entre les environnements
- Facilité de déploiement et de mise à l’échelle
- Isolation des dépendances
- Portabilité sur différentes plateformes
En maîtrisant Docker, vous pouvez déployer vos applications React de manière plus fiable et efficace, que ce soit en développement, en test ou en production.
Prochaines étapes
- Explorez Kubernetes pour l’orchestration
- Implémentez le monitoring avec Prometheus
- Optimisez les performances avec des CDN
- Mettez en place des pipelines CI/CD avancés
Commentaires
Les commentaires sont alimentés par GitHub Discussions
Connectez-vous avec GitHub pour participer à la discussion