ANAVEM
Référence
Languageen
Comment déployer un proxy inverse Nginx avec des conteneurs Docker

Comment déployer un proxy inverse Nginx avec des conteneurs Docker

Déployer un proxy inverse Nginx prêt pour la production en utilisant des conteneurs Docker avec des certificats SSL automatisés et une découverte de services dynamique pour plusieurs applications web.

Emanuel DE ALMEIDAEmanuel DE ALMEIDA
16 mars 2026 18 min 6
harddocker 9 étapes 18 min

Pourquoi déployer Nginx comme proxy inverse avec Docker ?

Un proxy inverse agit comme un intermédiaire entre les clients et vos services backend, fournissant un point d'entrée unique pour plusieurs applications. Lorsqu'il est conteneurisé avec Docker, Nginx devient un puissant directeur de trafic qui peut découvrir automatiquement les services, gérer les certificats SSL et fournir un équilibrage de charge sans modifications manuelles de configuration.

Qu'est-ce qui rend les proxies inverses basés sur Docker essentiels pour les applications modernes ?

Les configurations traditionnelles de proxy inverse nécessitent une configuration manuelle pour chaque nouveau service, la gestion des certificats et des règles complexes d'équilibrage de charge. Les solutions basées sur Docker comme nginxproxy/nginx-proxy éliminent cette surcharge en détectant automatiquement les nouveaux conteneurs et en configurant les routes en fonction des variables d'environnement. Cette approche est particulièrement précieuse dans les architectures de microservices où les services évoluent fréquemment.

Comment fonctionne la gestion automatisée des certificats SSL avec Docker ?

La combinaison de nginx-proxy et acme-companion offre une provision de certificats SSL sans intervention grâce à Let's Encrypt. Lorsque vous déployez un nouveau service avec les variables d'environnement appropriées, le système demande, valide et installe automatiquement les certificats SSL. Le renouvellement des certificats se fait automatiquement en arrière-plan, éliminant la surcharge manuelle qui rend traditionnellement la gestion des SSL complexe dans les environnements multi-services.

Guide de mise en oeuvre

Procédure complète

01

Installer Docker et Docker Compose

Tout d'abord, installez la dernière version de Docker Engine et Docker Compose. Nous utiliserons le script d'installation officiel pour Docker 27.1.0+.

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

Installez Docker Compose v2.29.2 :

sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.2/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

Déconnectez-vous et reconnectez-vous pour appliquer l'appartenance au groupe docker, puis vérifiez l'installation :

docker --version
docker-compose --version
Avertissement : Docker 27.1+ applique une sécurité de socket plus stricte. Utilisez toujours des montages en lecture seule (:ro) pour /var/run/docker.sock en production.
02

Créer la structure de répertoire du projet

Configurez une structure de répertoires propre pour votre configuration de proxy inverse. Cette organisation facilite la maintenance à mesure que vous ajoutez plus de services.

mkdir -p ~/nginx-proxy/{config,ssl,logs}
cd ~/nginx-proxy

Créez le fichier principal Docker Compose qui orchestrera notre configuration de proxy inverse :

touch docker-compose.yml

Vérifiez la structure :

tree ~/nginx-proxy
# Devrait afficher :
# nginx-proxy/
# ├── config/
# ├── docker-compose.yml
# ├── logs/
# └── ssl/
Astuce pro : Gardez votre configuration de proxy dans un répertoire dédié séparé de vos services d'application. Cela rend la sauvegarde et la migration beaucoup plus simples.
03

Configurer le proxy Nginx automatisé avec SSL

Créez la configuration principale de Docker Compose en utilisant les dernières images nginxproxy. Cette configuration offre la découverte automatique des services et la gestion des certificats SSL.

version: '3.8'

services:
  nginx-proxy:
    image: nginxproxy/nginx-proxy:1.3.0
    container_name: nginx-proxy
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - certs:/etc/nginx/certs
      - html:/usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./config:/etc/nginx/conf.d
      - ./logs:/var/log/nginx
    environment:
      - DEFAULT_HOST=yourdomain.com
    networks:
      - nginx-reverse-proxy
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"

  acme-companion:
    image: nginxproxy/acme-companion:2.5.1
    container_name: nginx-proxy-acme
    restart: always
    depends_on:
      - nginx-proxy
    environment:
      - DEFAULT_EMAIL=your@email.com
      - NGINX_PROXY_CONTAINER=nginx-proxy
    volumes:
      - certs:/etc/nginx/certs
      - html:/usr/share/nginx/html
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - acme:/etc/acme.sh
    networks:
      - nginx-reverse-proxy

networks:
  nginx-reverse-proxy:
    driver: bridge

volumes:
  certs:
  html:
  acme:

Remplacez your@email.com par votre adresse email réelle pour les notifications Let's Encrypt. Démarrez le proxy :

docker-compose up -d

Vérifiez que les deux conteneurs sont en cours d'exécution :

docker-compose ps
# Devrait montrer nginx-proxy et nginx-proxy-acme comme "Up"
04

Déployer une application backend de test

Créez une application de test simple pour vérifier que notre proxy inverse fonctionne correctement. Nous utiliserons une application Node.js basique qui affiche le nom d'hôte du conteneur.

Créez un nouveau répertoire pour l'application de test :

mkdir ~/test-app && cd ~/test-app

Créez une application Node.js simple :

// app.js
const express = require('express');
const os = require('os');
const app = express();
const PORT = 3000;

app.get('/', (req, res) => {
  res.json({
    message: 'Hello from reverse proxy!',
    hostname: os.hostname(),
    timestamp: new Date().toISOString(),
    headers: req.headers
  });
});

app.listen(PORT, '0.0.0.0', () => {
  console.log(`Server running on port ${PORT}`);
});

Créez le Dockerfile :

FROM node:18-alpine
WORKDIR /app
RUN npm init -y && npm install express
COPY app.js .
EXPOSE 3000
CMD ["node", "app.js"]

Construisez et testez l'application :

docker build -t test-app .
docker run -d --name test-backend \
  --network nginx-proxy_nginx-reverse-proxy \
  -e VIRTUAL_HOST=app.yourdomain.com \
  -e LETSENCRYPT_HOST=app.yourdomain.com \
  -e VIRTUAL_PORT=3000 \
  test-app

Vérifiez que le backend fonctionne et est connecté au réseau du proxy :

docker logs test-backend
docker network inspect nginx-proxy_nginx-reverse-proxy
05

Configurer les paramètres personnalisés de Nginx

Créez des configurations Nginx personnalisées pour des paramètres de proxy avancés tels que les délais d'attente, les tailles de tampon et les en-têtes de sécurité. Cette étape est cruciale pour les déploiements en production.

Créez un fichier de configuration personnalisé dans le répertoire config :

cd ~/nginx-proxy/config

Créez proxy.conf avec des paramètres prêts pour la production :

# proxy.conf
client_max_body_size 100M;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;
proxy_busy_buffers_size 16k;

# En-têtes 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;

# Transfert d'IP réelle
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

Créez gzip.conf pour la compression :

# gzip.conf
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/json
    application/javascript
    application/xml+rss
    application/atom+xml
    image/svg+xml;

Redémarrez le proxy pour appliquer la nouvelle configuration :

cd ~/nginx-proxy
docker-compose restart nginx-proxy

Vérifiez que la configuration est chargée sans erreurs :

docker-compose logs nginx-proxy | grep -i error
Astuce pro : Testez toujours les modifications de configuration dans un environnement de préproduction d'abord. Utilisez docker exec nginx-proxy nginx -t pour valider la syntaxe avant de redémarrer.
06

Set Up SSL Certificate Monitoring

Monitor SSL certificate status and renewal to prevent unexpected certificate expiration. The ACME companion handles renewal automatically, but monitoring ensures everything works correctly.

Check current certificate status:

docker exec nginx-proxy-acme /app/cert_status

Create a monitoring script to check certificate expiration:

#!/bin/bash
# cert-monitor.sh
DOMAINS=("app.yourdomain.com" "api.yourdomain.com")
WARN_DAYS=30

for domain in "${DOMAINS[@]}"; do
    expiry=$(docker exec nginx-proxy openssl x509 -in "/etc/nginx/certs/${domain}.crt" -noout -enddate 2>/dev/null | cut -d= -f2)
    if [ ! -z "$expiry" ]; then
        expiry_epoch=$(date -d "$expiry" +%s)
        current_epoch=$(date +%s)
        days_until_expiry=$(( (expiry_epoch - current_epoch) / 86400 ))
        
        if [ $days_until_expiry -lt $WARN_DAYS ]; then
            echo "WARNING: Certificate for $domain expires in $days_until_expiry days"
        else
            echo "OK: Certificate for $domain expires in $days_until_expiry days"
        fi
    else
        echo "ERROR: No certificate found for $domain"
    fi
done

Make the script executable and test it:

chmod +x cert-monitor.sh
./cert-monitor.sh

Add to crontab for daily monitoring:

echo "0 9 * * * /home/$(whoami)/nginx-proxy/cert-monitor.sh | logger -t cert-monitor" | crontab -

Verify the ACME companion is working by checking logs:

docker-compose logs acme-companion | tail -20
07

Ajouter plusieurs services backend

Démontrez comment ajouter plusieurs services derrière le proxy inverse. Cela montre la véritable puissance de la configuration de proxy automatisée pour l'architecture de microservices.

Créez un deuxième service de test (API backend) :

mkdir ~/api-service && cd ~/api-service

Créez un service API simple :

// api.js
const express = require('express');
const app = express();
const PORT = 4000;

app.get('/health', (req, res) => {
  res.json({ status: 'healthy', service: 'api', version: '1.0.0' });
});

app.get('/users', (req, res) => {
  res.json({
    users: [
      { id: 1, name: 'John Doe' },
      { id: 2, name: 'Jane Smith' }
    ]
  });
});

app.listen(PORT, '0.0.0.0', () => {
  console.log(`API service running on port ${PORT}`);
});

Créez un Dockerfile pour le service API :

FROM node:18-alpine
WORKDIR /app
RUN npm init -y && npm install express
COPY api.js .
EXPOSE 4000
CMD ["node", "api.js"]

Construisez et déployez le service API :

docker build -t api-service .
docker run -d --name api-backend \
  --network nginx-proxy_nginx-reverse-proxy \
  -e VIRTUAL_HOST=api.yourdomain.com \
  -e LETSENCRYPT_HOST=api.yourdomain.com \
  -e VIRTUAL_PORT=4000 \
  api-service

Testez les deux services via le proxy :

curl -H "Host: app.yourdomain.com" http://localhost/
curl -H "Host: api.yourdomain.com" http://localhost/health

Vérifiez que les certificats SSL ont été générés automatiquement :

docker exec nginx-proxy ls -la /etc/nginx/certs/ | grep -E "(app|api).yourdomain.com"
Avertissement : Chaque nouveau service doit être sur le même réseau Docker que le proxy. Les services sur des réseaux différents ne seront pas découverts automatiquement.
08

Configurer l'équilibrage de charge et les vérifications de santé

Configurez l'équilibrage de charge pour les services à haute disponibilité et implémentez des vérifications de santé pour garantir que le trafic ne va qu'aux backends sains.

Créez un service équilibré en charge avec plusieurs instances :

cd ~/nginx-proxy

Ajoutez une configuration de service équilibré en charge à votre docker-compose.yml :

  web-app-1:
    image: test-app
    container_name: web-app-1
    environment:
      - VIRTUAL_HOST=lb.yourdomain.com
      - LETSENCRYPT_HOST=lb.yourdomain.com
      - VIRTUAL_PORT=3000
    networks:
      - nginx-reverse-proxy
    restart: unless-stopped

  web-app-2:
    image: test-app
    container_name: web-app-2
    environment:
      - VIRTUAL_HOST=lb.yourdomain.com
      - LETSENCRYPT_HOST=lb.yourdomain.com
      - VIRTUAL_PORT=3000
    networks:
      - nginx-reverse-proxy
    restart: unless-stopped

Créez une configuration upstream personnalisée pour les vérifications de santé :

# config/lb.yourdomain.com_location
location /health {
    access_log off;
    return 200 "healthy\n";
    add_header Content-Type text/plain;
}

location / {
    proxy_pass http://lb.yourdomain.com;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    
    # Paramètres de vérification de santé
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
    proxy_connect_timeout 5s;
    proxy_send_timeout 10s;
    proxy_read_timeout 10s;
}

Déployez les services équilibrés en charge :

docker-compose up -d web-app-1 web-app-2

Testez l'équilibrage de charge en effectuant plusieurs requêtes :

for i in {1..6}; do
  curl -s -H "Host: lb.yourdomain.com" http://localhost/ | jq .hostname
done

Vous devriez voir les requêtes réparties entre différents noms d'hôte de conteneur, confirmant que l'équilibrage de charge fonctionne.

09

Mettre en œuvre la surveillance et la journalisation

Configurez une surveillance et une journalisation complètes pour votre proxy inverse afin de suivre les performances, les erreurs et les événements de sécurité.

Créez un format de journal Nginx personnalisé pour une meilleure surveillance :

# config/log_format.conf
log_format proxy_log '$remote_addr - $remote_user [$time_local] '
                     '"$request" $status $body_bytes_sent '
                     '"$http_referer" "$http_user_agent" '
                     '$request_time $upstream_response_time '
                     '$upstream_addr $upstream_status';

access_log /var/log/nginx/access.log proxy_log;

Créez une configuration de rotation des journaux :

# /etc/logrotate.d/nginx-proxy
~/nginx-proxy/logs/*.log {
    daily
    missingok
    rotate 52
    compress
    delaycompress
    notifempty
    create 644 root root
    postrotate
        docker exec nginx-proxy nginx -s reload
    endscript
}

Configurez un script de surveillance simple :

#!/bin/bash
# monitor-proxy.sh
LOG_FILE="~/nginx-proxy/logs/access.log"
ERROR_THRESHOLD=10
TIME_WINDOW="1 minute ago"

# Vérifiez les taux d'erreur élevés
ERROR_COUNT=$(grep -c " 5[0-9][0-9] " $LOG_FILE | tail -100)
if [ $ERROR_COUNT -gt $ERROR_THRESHOLD ]; then
    echo "TAUX D'ERREUR ÉLEVÉ : $ERROR_COUNT erreurs 5xx détectées"
fi

# Vérifiez la santé du proxy
docker-compose ps | grep -q "Up" || echo "ALERTE : Les conteneurs proxy ne fonctionnent pas"

# Vérifiez l'espace disque pour les journaux
DISK_USAGE=$(df ~/nginx-proxy/logs | tail -1 | awk '{print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 80 ]; then
    echo "AVERTISSEMENT : Utilisation du disque des journaux à ${DISK_USAGE}%"
fi

# Vérifiez l'expiration des certificats
./cert-monitor.sh

Rendez le script de surveillance exécutable et ajoutez-le à cron :

chmod +x monitor-proxy.sh
echo "*/5 * * * * /home/$(whoami)/nginx-proxy/monitor-proxy.sh" | crontab -

Testez la configuration complète en vérifiant tous les services :

docker-compose ps
docker-compose logs --tail=50
curl -I https://app.yourdomain.com
curl -I https://api.yourdomain.com
Astuce pro : Utilisez des outils comme Prometheus et Grafana pour une surveillance avancée. Le nginx-prometheus-exporter peut fournir des métriques détaillées pour les environnements de production.

Questions Fréquentes

Comment dépanner nginx-proxy qui ne détecte pas mes conteneurs Docker ?+
Assurez-vous que vos conteneurs sont sur le même réseau Docker que nginx-proxy (généralement nginx-proxy_nginx-reverse-proxy). Vérifiez que vous avez correctement défini la variable d'environnement VIRTUAL_HOST et que le conteneur est effectivement en cours d'exécution. Utilisez 'docker network inspect nginx-proxy_nginx-reverse-proxy' pour vérifier la connectivité réseau et 'docker-compose logs nginx-proxy' pour voir si le proxy a détecté votre service.
Quelle est la différence entre nginx-proxy et la configuration manuelle de Nginx dans Docker ?+
La configuration manuelle de Nginx nécessite l'édition de fichiers de configuration et le redémarrage des conteneurs pour chaque nouveau service. nginx-proxy génère automatiquement des configurations en surveillant les événements Docker et en lisant les variables d'environnement des conteneurs. Cela signifie que vous pouvez déployer de nouveaux services sans toucher à la configuration du proxy, ce qui le rend idéal pour les environnements dynamiques et les pipelines CI/CD.
Comment puis-je configurer des paramètres Nginx personnalisés avec nginxproxy/nginx-proxy ?+
Créez des fichiers de configuration au format 'domaine.com_emplacement' ou 'domaine.com' dans votre répertoire de configuration monté. Pour les paramètres globaux, utilisez des fichiers comme 'proxy.conf' ou 'gzip.conf'. Vous pouvez également définir des configurations par conteneur en utilisant des variables d'environnement comme VIRTUAL_PROTO=https ou VIRTUAL_PORT=8080. Le proxy inclut automatiquement ces configurations personnalisées lors de la génération de la configuration finale de Nginx.
Pourquoi mes certificats Let's Encrypt ne se renouvellent-ils pas automatiquement ?+
Vérifiez que le conteneur acme-companion est en cours d'exécution et a accès au socket Docker avec des permissions en lecture seule. Assurez-vous que votre variable d'environnement DEFAULT_EMAIL est définie et que les ports 80 et 443 sont accessibles depuis Internet pour la validation de domaine. Utilisez 'docker-compose logs acme-companion' pour vérifier les erreurs de renouvellement. Le renouvellement des certificats se produit généralement 30 jours avant l'expiration.
Comment configurer l'équilibrage de charge pour plusieurs instances du même service ?+
Déployez plusieurs conteneurs avec des variables d'environnement VIRTUAL_HOST identiques. nginx-proxy détecte automatiquement plusieurs conteneurs avec le même nom d'hôte et configure l'équilibrage de charge en amont en utilisant le round-robin par défaut. Vous pouvez personnaliser le comportement de l'équilibrage de charge en créant des fichiers de configuration en amont dans votre répertoire de configuration ou en utilisant des variables d'environnement comme VIRTUAL_PROTO et les paramètres de vérification de l'état.
Emanuel DE ALMEIDA
Écrit par

Emanuel DE ALMEIDA

Microsoft MCSA-certified Cloud Architect | Fortinet-focused. I modernize cloud, hybrid & on-prem infrastructure for reliability, security, performance and cost control - sharing field-tested ops & troubleshooting.

Discussion

Partagez vos réflexions et analyses

Vous devez être connecté pour commenter.

Chargement des commentaires...