Rechercher
  • Anthony Maréchal

Utiliser nginx en tant que reverse proxy vers des containers docker

Présentation


Lorsque l'on fait quelques recherches sur l'utilisation de nginx avec docker, on trouve assez facilement des ressources utilisant un container nginx associé aux autres containers d'un docker-compose ou de simples containers docker lancés via un docker run.


Si cette solution est, à n'en point douter tout à fait satisfaisante d'un point de vue technique, elle pêche à mon avis concernant l'évolutivité et la centralisation des domaines et sous-domaines associés.


La solution qui sera ici présentée sera légèrement différente.


On visera ici la mise en place d'un service nginx local au serveur, sur lequel se trouvent un certain nombre de containers docker de type service web (apache, light httpd ou nginx, peu importe).



Image issue du site https://www.bogotobogo.com/DevOps/Docker/Docker-Compose-Nginx-Reverse-Proxy-Multiple-Containers.php


L'avantage étant également de pouvoir synchroniser le cache HTTP au niveau du serveur nginx.


Intégration SSL


Dans la solution ici proposée, nous sommes sur une stratégie de chiffrage des flux en mode Hard Outside / Soft Inside.

En effet, on déporte sur le service nginx la responsabilité de gérer les certificats SSL et de reporter les flux en HTTP vers les containers, n'écoutant que le port 80.


Intégration de Varnish


L'avantage complémentaire de cette solution est de pouvoir placer un Varnish (soit local, soit dans un container) pour gérer le cache HTTP.

Ce point a une pertinence lorsque l'on veut ne pas trop charger nginx avec le cache et le dédier à Varnish, ce qui permet à nginx de se concentrer sur son rôle de reverse proxy.


Mise en place


Afin d'implémenter cette solution, il convient dans un premier temps de monter un service nginx sur le serveur.


sur une debian ou ubuntu, un simple :


apt-get install nginx

fera parfaitement le job.


Prenons un cas assez simple, un apache qui fait un hello world :


version: "3"


services:

  apache-hello:
      image: tutum/hello-world
      restart: always
      ports:
        - "35000:80"

Nous allons donc avoir ici tous les appels sur le port 35000 renvoyés sur le port 80 de l'apache.


Ensuite, on crée le fichier hello :

/etc/nginx/sites-available/hello80

On inserre :


server {
        listen 80 ;


        server_name hello.yourdomain.com;


        location /.well-known {
                alias /var/www/html/hello.yourdomain.com/.well-known;
        }

}

On crée les répertoires qui vont bien pour la certification de letsencrypt :


mkdir /var/www/html/hello.yourdomain.com
mkdir /var/www/html/hello.yourdomain.com/.well-known

Ensuite, on active la conf d'écoute du port 80 dans nginx :


ln -s /etc/nginx/sites-available/hello80 /etc/nginx/sites-enabled/hello80

sudo service nginx reload

Puis on fait générer le certificat ssl par letsencrypt :


certbot-auto certonly --webroot -w /var/www/html/hello.yoursite.com -d hello.yoursite.com

ensuite, on crée le fichier


/etc/nginx/sites-available/hello

et on le renseigne comme suit :


upstream hello{
    server 127.0.0.1:35000;
}

server {
        listen 80 ;
        #permet de gérer le routage vers le port 443 de manière automatique


        server_name hello.yoursite.com;
        location / {
                return         301 https://$server_name$request_uri;
                
        }

}

server {
        listen 443 ssl;

        proxy_redirect off;
        server_name hello.yoursite.com;
        ssl_certificate /etc/letsencrypt/live/hello.yoursite.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/hello.yoursite.com/privkey.pem;


        location / {
                proxy_pass http://hello;
                proxy_set_header Host $host;
                # A noter, on peut ici ajouter de nombreuses choses lorsque c'est nécessaire (transmission ou non des headers etc. )
        }

	location /.well-known {
                alias /var/www/html/hello.yoursite.com/.well-known;
        }
}

On supprime l'ancien hello80 des sites available puis on met le nouveau à la place


rm /etc/nginx/sites-available/hello80
ln -s /etc/nginx/sites-available/hello /etc/nginx/sites-enabled/hello

service nginx reload

Et on a désormais un superbe site en https exposé,


Bien entendu, l'avantage de tout ça est que ça peut être totalement scripté et automatisé.

Voire, la mise en place d'un serveur dédié pour nginx (ou une VM, chacun ses choix), qui route ensuite vers les serveurs physiques différents hébergeant les containers.


A noter, les quelques subtilités de ce fichier hello pour nginx :

upstream hello{
    server 127.0.0.1:35000;
}

Ce point est crucial pour mieux dormir lorsque vous jouez avec du multi containers. Cela permet de créer un groupe de nommage, voire d'utiliser des groupes de serveurs.

Sans cela, vous risquez d'avoir quelques plantages fort désagréables sur le nginx restart...


proxy_pass http://hello;
proxy_set_header Host $host;

Ici, on renvoie en https vers le hello définit dans l'upstream plus haut, et on transferre tous les headers associés aux appels http (par exemple pour gérer les tokens d'autorisation jwt ou autre)


Et enfin

	location /.well-known {
                alias /var/www/html/hello.yoursite.com/.well-known;
        }


C'est ce qui permet de gérer les renouvellements de certificats lors du certbot-auto renew.

A noter, dans les anciennes versions de certbot, cela se faisait sur le port 80, mais depuis 2019, cela passe par le https. Si vous utilisez une vieille version de certbot, il pourrait être nécessaire de placer ce location dans la zone définissant les règles de l'écoute sur le port 80.


Voilà.


P.C : J'ai mis les fichiers dans un repo github : https://github.com/totoskul/nginx-docker




35 vues0 commentaire
Rejoignez notre équipe
arrow&v

Merci pour votre envoi !