4
votes

Remplacer les variables d'environnement dans la configuration NGINX depuis docker-compose

J'essaye de démarrer un serveur NGINX dans un conteneur docker configuré via docker-compose. Le hic, cependant, est que je voudrais substituer une variable d'environnement à l'intérieur de la section http, spécifiquement dans le bloc "amont".

Ce serait génial que cela fonctionne, car j'ai plusieurs autres conteneurs qui sont tous configurés via des variables d'environnement, et j'ai environ 5 environnements qui doivent être exécutés à tout moment. J'ai essayé d'utiliser "envsubst" (comme suggéré par la documentation officielle de NGINX), perl_set et set_by_lua, mais aucun d'entre eux ne semble fonctionner.

Voici la configuration de NGINX, car elle est après mon plus essai récent

qa3_front_end       | 2019/06/18 12:49:02 [emerg] 1#1: no "events" section in configuration
qa3_front_end       | nginx: [emerg] no "events" section in configuration
qa3_front_end exited with code 1

Ci-dessous le fichier docker de NGINX

qa3_front_end       | 2019/06/18 12:35:36 [emerg] 1#1: host not found in upstream "${nginx_upstream}" in /etc/nginx/nginx.conf:19
qa3_front_end       | nginx: [emerg] host not found in upstream "${nginx_upstream}" in /etc/nginx/nginx.conf:19
qa3_front_end exited with code 1

Ci-dessous se trouve la section du docker-compose.yml pour le Serveur NGINX (avec noms et adresses IP modifiés). La commande envsubst est intentionnellement commentée à ce stade de mon dépannage.

front-end:
        environment:
            - NGINXPROXY=172.31.67.100:9300
        build: http://gitaccount:password@gitserver.com/group/front-end.git#develop
        container_name: qa_front_end
        image: qa-front-end
        restart: always
        networks:
            qa_network:
                ipv4_address: 172.28.0.215
        ports:
            - "9080:80"
        # command: /bin/bash -c "envsubst '$$NGINXPROXY' < /etc/nginx/nginx.conf > /etc/nginx/nginx.conf && nginx -g 'daemon off;'"

Ce qui semble se produire, c'est lorsque je référence la variable $ nginxproxy dans le bloc en amont (juste après " server "), j'obtiens une sortie qui donne l'impression de faire référence à la chaîne littérale" $ nginxproxy "plutôt que de substituer la valeur de la variable.

# build stage
FROM node:latest
WORKDIR /app
COPY ./ /app
RUN npm install
RUN npm run build

# production stage
FROM nginx:1.17.0-perl
COPY --from=0 /app/dist /usr/share/nginx/html
RUN apt-get update && apt-get install -y gettext-base
RUN rm /etc/nginx/conf.d/default.conf
RUN rm /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d
COPY nginx.conf /etc/nginx
RUN mkdir /certs
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]

Quand j'essaye d'utiliser envsubst, j'obtiens une erreur qui donne l'impression que la commande a foiré le format du fichier nginx.conf

user  nginx;
worker_processes  1;
env NGINXPROXY;

load_module modules/ngx_http_perl_module.so;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
    perl_set $nginxproxy 'sub { return $ENV{"NGINXPROXY"}; }';

    upstream api-upstream {
        server ${nginxproxy};
    }

    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;

    sendfile        off;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

Je suis assez coincé, alors merci d'avance pour votre aide.


0 commentaires

3 Réponses :


7
votes

Vous pouvez éviter certains tracas avec l'interprétation des variables d'environnement de Compose en définissant votre propre point d'entrée. Voir cet exemple simple:

  • entrypoint.sh (assurez-vous que ce fichier est exécutable)
command: ["/bin/bash", "-c", "export NGINXPROXY && envsubst '$$NGINXPROXY' < /etc/nginx/nginx.conf > /etc/nginx/nginx.conf && nginx -g 'daemon off;'"]
  • docker-compose.yml
version: "3.7"

services:
    front-end:
        image: nginx
        environment:
            - NGINXPROXY=172.31.67.100:9300
        ports:
            - 80:80
        volumes:
            - ./config:/config.template
            - ./entrypoint.sh:/entrypoint.sh
        entrypoint: ["/entrypoint.sh"]
        command: ["nginx", "-g", "daemon off;"]

Mon fichier config a le même contenu que votre nginx.conf , mis à part le fait que je devais commentez les lignes en utilisant le module Perl.

Notez que j'ai dû monter mon fichier de configuration à un autre emplacement avant de pouvoir le l'envoyer . J'ai rencontré un comportement étrange sous la forme que le fichier finit par être vide après la substitution, ce qui peut être évité par cette approche. Cela ne devrait pas poser de problème dans votre cas particulier, car vous l'avez déjà intégré dans votre image au moment de la construction.


MODIFIER

Pour exhaustivité, pour modifier le moins possible votre configuration, il vous suffit de vous assurer que vous exportez votre variable d'environnement. Adaptez votre commande comme ceci:

#!/bin/sh

export NGINXPROXY

envsubst '${NGINXPROXY}' < /config.template > /etc/nginx/nginx.conf

exec "$@"

... et vous devriez être prêt à partir. Cependant, je recommanderais toujours la méthode "plus propre" pour définir votre propre point d'entrée.


1 commentaires

Je pourrais COPY ce script dans le Dockerfile et le spécifier comme ENTRYPOINT de l'image, plutôt que de le remplacer uniquement au moment de l'exécution.



4
votes

Donc, après avoir lutté avec ce problème, j'ai réussi à le faire fonctionner de la même manière que la réponse fournie par bellackn. Je vais poster ma solution exacte ici, au cas où quelqu'un d'autre aurait besoin de référencer une solution complète.

Étape 1: Écrivez votre nginx.conf ou default.conf comme vous l'écririez normalement. Enregistrez le fichier sous "nginx.conf.template" ou "default.conf.template" en fonction de celui dans lequel vous essayez de remplacer les variables.

version: '2.0'
services:
    front-end:
        environment:
            - SERVER_NAME=172.31.67.100:9100
        build: http://git-account:git-password@git-server.com/project-group/repository-name.git#branch-ame
        container_name: qa_front_end
        image: qa-front-end-vue
        restart: always
        networks:
            qa_network:
                ipv4_address: 172.28.0.215
        ports:
            - "9080:80"
        command: >
            /bin/sh -c
            "envsubst '
            $${SERVER_NAME}
            '< /etc/nginx/nginx.conf.template
            > /etc/nginx/nginx.conf
            && nginx -g 'daemon off;'"

Étape 2: Remplacez un variable au format $ {VARNAME} pour la ou les valeurs que vous souhaitez remplacer par une variable d'environnement:

# build stage
FROM node:latest
WORKDIR /app
COPY ./ /app
RUN npm install
RUN npm run build

# production stage
FROM nginx:1.17.0-perl
COPY --from=0 /app/dist /usr/share/nginx/html
RUN apt-get update && apt-get install -y gettext-base
RUN rm /etc/nginx/conf.d/default.conf
RUN rm /etc/nginx/nginx.conf
#-----------------------------------#
|COPY default.conf /etc/nginx/conf.d|
|COPY nginx.conf.template /etc/nginx|
#-----------------------------------#
RUN mkdir /certs
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]

Étape 3: Dans votre fichier docker, copiez votre nginx fichiers de configuration (votre nginx.conf.template ou default.conf.template) dans votre conteneur à l'emplacement approprié:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
    upstream api-upstream {
        server ${SERVER_NAME};
    }

    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;

    sendfile        off;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

Étape 4: Définissez votre variable d'environnement dans votre docker- compos.yml en utilisant l'étiquette de section "environnement". Assurez-vous que le nom de votre variable d'environnement correspond au nom de variable que vous avez choisi dans votre fichier de configuration nginx. Utilisez la commande «envsubt» dans votre conteneur docker pour remplacer les valeurs de vos variables par vos variables dans votre nginx.conf.template et écrivez la sortie dans un fichier nommé nginx.conf à l'emplacement correct. Cela peut être fait dans le fichier docker-compose.yml en utilisant le libellé de la section "command":

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
    upstream api-upstream {
        server 192.168.25.254;
    }

    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;

    sendfile        off;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

Étape 5: Exécutez votre pile avec docker-compose up (avec tout commutateurs supplémentaires dont vous avez besoin) et votre serveur nginx devrait maintenant commencer avec la valeur que vous avez fournie dans la section "environnement" de votre docker-compose.yml

Comme mentionné dans la solution ci-dessus, vous pouvez également définir votre propre point d'entrée, mais cette solution a également prouvé qu'elle fonctionnait plutôt bien et conserve tout ce qui est contenu dans un seul fichier de configuration, me donnant la possibilité d'exécuter une pile de services directement à partir de git avec rien d'autre qu'un fichier docker-compose.yml. p>

Un grand merci à tous ceux qui ont pris le temps de se préparer, et bellackn d'avoir pris le temps de m'aider à résoudre le problème.


0 commentaires

9
votes

Depuis nginx 1.19 , vous pouvez désormais utiliser des variables d'environnement dans votre configuration avec docker-compose. J'ai utilisé la configuration suivante:

# file: docker/nginx/templates/default.conf.conf
upstream api-upstream {
    server ${API_HOST};
}


# file: docker-compose.yml
services:
    nginx:
        image: nginx:1.19-alpine
        volumes:
            - "./docker/nginx/templates:/etc/nginx/templates/"
        environment:
            NGINX_ENVSUBST_TEMPLATE_SUFFIX: ".conf"
            API_HOST: api.example.com
        

Je sors un peu du script de l'exemple de la documentation. Notez l'extension supplémentaire .conf sur le fichier modèle - ce n'est pas une faute de frappe. Dans la documentation de l'image nginx, il est suggéré de nommer le fichier, par exemple, default.conf.template . Au démarrage, un script prendra ce fichier, remplacera les variables d'environnement, puis sortira le fichier vers /etc/nginx/conf.d/ avec le nom de fichier d'origine, en supprimant le suffixe .template .

Par défaut, ce suffixe est .template , mais cela interrompt la coloration syntaxique à moins que vous ne configuriez votre éditeur. Au lieu de cela, j'ai spécifié .conf comme suffixe de modèle. Si vous ne nommez votre fichier que default.conf , le résultat sera un fichier nommé /etc/nginx/conf.d/default et votre site ne sera pas servi comme prévu.

p>


2 commentaires

Juste un petit point de clarification: ce fichier doit être dans le répertoire des templates du conteneur nginx. Si vous utilisiez un volume de composition docker ./docker/nginx/conf.d/:/etc/nginx/conf.d/ pour gérer ce fichier, vous devrez le changer en ./ docker / nginx / templates /: / etc / nginx / templates / à la place


@JosephMarikle bonne idée, j'ai mis à jour l'exemple pour refléter votre commentaire