Table des matières

, ,

Nginx avec Docker

On peut facilement lancer l'imge officielle en test, ici on utilise le tag stable-alpine plus léger que la version stable (~20 Mo contre 130 Mo):

docker run --rm --name webserver -d -p 8088:80 -d nginx:stable-alpine

# Pour mapper les documents locaux sur le root web du conteneur 
docker run --rm --name webserver -d -p 8088:80 \
-v /some/content:/usr/share/nginx/html:ro -d nginx:stable-alpine

Via le navigateur, le site par défaut en HTTP est accessible à l'URL http://localhost:8088

Modifier la configuration

Il est possible d'extraire le fichier de configuration par défaut du container, de le modifier et de relancer un conteneur avec la nouvelle configuration:

# lancement d'un conteneur nginx
docker run --rm --name tmp_nginx -d nginx:stable-alpine
 
# Extraire le fichier de configuration du conteneur dans le répertoire courant
docker cp tmp_nginx:/etc/nginx/conf.d/default.conf .
 
# Arrêter le conteneur
docker stop -f tmp_nginx
 
# Après modification du fichier de conf, il peut être mapper en lecture seule
# sur le nouveau conteneur
docker run --rm --name nginx -d -p 8088:80 \
-v ./default.conf:/etc/nginx/conf.d/default.conf:ro \
-d nginx:stable-alpine

On peut faire également faire le choix d'ouvrir un terminal interactif et de modifier le fichier de configuration depuis l’intérieur conteneur car celui-ci contient un système minimal Alpine Linux et un shell:

docker exec --tty --interactive container_name /bin/sh

Une fois dans le conteneur, on modifie le fichier /etc/nginx/conf.d/default.conf

Pour charger la nouvelle configuration:

# demander au processus en cours d’exécution de recharger la conf modifiée
nginx -s reload

Une fois le fichier de configuration souhaité obtenu, on pourra l'extraire du conteneur avec la commande docker cp puis l'utiliser pour générer une image personnalisée via un Dockerfile:

# copier le fichier du conteneur dans le répertoire courant
docker cp container_name:/etc/nginx/conf.d/default.conf .

Le Dockerfile ci-dessous utilisera la nouvelle configuration valide:

FROM nginx:stable-alpine
COPY default.conf /etc/nginx/conf.d/default.conf
...

https

Ici on modifie la configuration de nginx, il faudra fournir le certificat et la clé privée.

default.conf
server {
    listen       80;
    listen       443 ssl;
    listen  [::]:80;
    listen  [::]:443 ssl;
    keepalive_timeout   70;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
 
    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;
 
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
 
    #error_page  404              /404.html;
 
    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
 
    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}
 
    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}
 
    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

Le répertoire courant contient:

Dockerfile
FROM nginx:stable-alpine
COPY default.conf /etc/nginx/conf.d/
COPY www.example.com.crt /etc/nginx
COPY www.example.com.key /etc/nginx
 
EXPOSE 80/tcp
EXPOSE 443/tcp

On peut lancer la construction de l'image puis l’exécution du conteneur:

# creation de l'image
docker image build --tag tnf/nginx:stable-alpine .
 
# creation et execution du conteneur
docker container run --detach --name nginx -p 80:80 -p 443:443 tnf/nginx:stable-alpine

Modifier le fichier /etc/hosts ou la configuration du DNS pour résoudre correctement www.example.com. Le site en https est accessible à l'URL https://www.example.com.

Execution de scripts shell

fcgiwrap permet d’exécuter des scripts shell. Utiliser le gestionnaire de paquetage propre à la distribution pour l'installer.

apk add fcgiwrap spawn-fcgi
spawn-fcgi -u fcgiwrap -g www-data -S -s /run/fcgiwrap/fcgiwrap.socket -P /run/fcgiwrap/fcgiwrap.pid -- /usr/bin/fcgiwrap

Troubleshooting

Lors de l’exécution d'un script CGI une page d'erreur est affichée (502), les logs indiquent:

2021/02/27 17:19:22 [error] 21#21: *1 upstream prematurely closed FastCGI stdout while reading response header from upstream, client: 172.21.0.2, server: red.labinfo.mairie.local, request: "GET /cgi HTTP/1.1", upstream: "fastcgi://unix:/run/fcgiwrap/fcgiwrap.socket:", host: "red.labinfo.mairie.local"

Cette erreur s'est produite lorsque:

  1. La configuration de la localisation sous nginx ne mentionnait pas le répertoire contenant les script via la directive root;
  2. Le script CGI ne commençait pas sa réponse avec un header minimal Content-type suivi de 2 retours à la ligne;
server {
  # ...
  
  location /info {
    gzip off;
    root /srv/fcgiwrap;
    access_log on;           # pour ne pas logger les accès 
    autoindex off;           # empeche l'indexation et affichage des dossier du serveur
    # include fastcgi_params;  # contient les noms des variables CGI /etc/nginx/fastcgi_params;
    fastcgi_param SCRIPT_FILENAME /srv/fcgiwrap/service_info.sh;
    fastcgi_pass unix:/run/fcgiwrap.sock;
    }

  # ...

}

Le script shell doit commencer par retourner le header minimal

#!/bin/sh
echo "Content-type: text/html"
echo ""
echo ""
 
...

Références