skip to Main Content

I would like to proxy_pass to the related service conditionally based on environment variable.. What I mean, prox_pass adress should be change based on NODE_ENV variable..

What is the best approach of doing this ? Can I use if statement like as below for proxy_pass? If yes how should I do this ? Apart from this, I tried to create a bash as below as below to pass environment variable to nginx but could not able to set and pass $NGINX_BACKEND_ADDRESS to nginx conf somehow. Any help will be appreciated

   if ($NODE_ENV == "development) {
       proxy_pass http://myservice-dev;
   }

nginx.conf

server {
    listen  3000;
    location / {
        root /usr/src/app;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
    location /csrf/token {
        proxy_pass ${NGINX_BACKEND_ADDRESS}/csrf/token;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
    location /export/apis {
        proxy_pass ${NGINX_BACKEND_ADDRESS}/export/apis;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

entrypoint.sh

#!/usr/bin/env sh
set -eu
export NODE_ENV=development
if ["$NODE_ENV" == "development"]
then
    export NGINX_BACKEND_ADDRESS=http://backend-dev
elif ["$NODE_ENV" == "stage"]
then
    export NGINX_BACKEND_ADDRESS=http://backend-stage
elif ["$NODE_ENV" == "development"
then
    export NGINX_BACKEND_ADDRESS=http://backend-preprod
elif ["$NODE_ENV" == "development"]
then
    export NGINX_BACKEND_ADDRESS=http://backend
else 
    echo "Error in reading environment variable in nginx-conf.sh."
fi
echo "Will proxy requests for  to ${NGINX_BACKEND_ADDRESS}*"
exec /nginx-conf.sh "$@"

Dockerfile

FROM nginx:alpine AS production-build
WORKDIR /usr/src/app
ARG NODE_ENVIRONMENT=development
ENV NODE_ENV=$NODE_ENVIRONMENT
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx.conf.template /etc/nginx/conf.d/default.conf.template
COPY nginx-conf.sh /
RUN chgrp -R root /var/cache/nginx /var/run /var/log/nginx /var/run/nginx.pid && 
    chmod -R 775 /var/cache/nginx /var/run /var/log/nginx /var/run/nginx.pid
USER nginx
COPY --from=builder /usr/src/app/dist .
ENTRYPOINT ["/nginx-conf.sh", $NODE_ENVIRONMENT]
EXPOSE 3000
CMD ["nginx", "-g", "daemon off;"]

3

Answers


  1. if you want to run an if statement in your dockerfile, then you can use the RUN command in the dockerfile, for example using bash,
    RUN if [[ -z "$arg" ]] ; then echo Argument not provided ; else echo Argument is $arg ; fi

    Login or Signup to reply.
  2. The way i normally do this is I have a generic nginx proxy and i then just pass in the url and protocol as env vars

    ubuntu@vps-f116ed9f:/opt/docker_projects/docker_examples/load_balancer$ cat proxy.conf
    server {
      listen 80 default_server;
    
      resolver 127.0.0.11 valid=1s;
    
      set $protocol $PROXY_PROTOCOL;
      set $upstream $PROXY_UPSTREAM;
    
      location / {
        proxy_pass $protocol://$upstream$request_uri;
    
        proxy_pass_header Authorization;
    
        proxy_http_version 1.1;
        proxy_ssl_server_name on;
        proxy_set_header Host $upstream;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Connection "";
    
        proxy_buffering off;
        proxy_read_timeout 5s;
        proxy_redirect off;
        proxy_ssl_verify off;
        client_max_body_size 0;
      }
    }
    
    ubuntu@vps-f116ed9f:/opt/docker_projects/docker_examples/load_balancer$ cat Dockerfile
    FROM nginx:1.13.8
    
    ENV PROXY_PROTOCOL=http PROXY_UPSTREAM=example.com
    
    COPY proxy.conf /etc/nginx/conf.d/default.template
    COPY start.sh /
    
    CMD ["/start.sh"]
    

    I then have a start script that will substitue the env vars into my proxy_config.

    ubuntu@vps-f116ed9f:/opt/docker_projects/docker_examples/load_balancer$ cat start.sh
    #!/usr/bin/env bash
    envsubst '$PROXY_PROTOCOL,$PROXY_UPSTREAM' < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf
    
    exec nginx -g 'daemon off;'
    
    Login or Signup to reply.
  3. The Docker Hub nginx image (as of nginx:1.19) has a facility to do environment-variable replacement in configuration files:

    […] this image has a function, which will extract environment variables before nginx starts. […] this function reads template files in /etc/nginx/templates/*.template and outputs the result of executing envsubst to /etc/nginx/conf.d.

    So your first step is to rename your configuration file as is (including proxy_pass ${NGINX_BACKEND_ADDRESS}/...) to something like default.conf.template and put it in the required directory.

    I would directly pass that address in your deploy-time configuration. I would not include it in the image in any way. (Imagine setups like "a developer is trying to run this stack on their local desktop system" where none of the URLs in the entrypoint script are right.) That also lets you get rid of pretty much all the code here; you would just have

    # Dockerfile
    FROM ... AS builder
    ...
    FROM nginx:1.21-alpine
    COPY nginx/nginx.conf.template /etc/nginx/conf.d/default.conf.template
    COPY --from=builder /usr/src/app/dist /usr/share/nginx/html
    # Permissions, filesystem layout, _etc._ are fine in the base image
    # Use the base image's ENTRYPOINT/CMD
    
    # docker-compose.yml
    version: '3.8'
    services:
      proxy:
        build: .
        ports: ['8000:80']
        environment:
          - NGINX_BACKEND_ADDRESS=https://backend-prod.example.com
    

    If you are in fact using Compose, you can use multiple docker-compose.yml files to provide settings for specific environments.

    # docker-compose.local.yml
    # Run the backend service locally too in development mode
    version: '3.8'
    services:
      backend: # not in docker-compose.yml
        build: backend
        # and other settings as required
      nginx: # overrides docker-compose.yml settings
        environment:
          - NGINX_BACKEND_ADDRESS=http://backend
        # no other settings
    
    docker-compose -f docker-compose.yml -f docker-compose.local.yml up
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search