Michal Zalecki
Michal Zalecki
software development, testing, JavaScript,
TypeScript, Node.js, React, and other stuff

NGINX: Listen on $PORT env in Docker

Each time I have to serve static files, NGINX is my default choice. I use it for this blog, which is generated using Gatsby, a few simple webflow static pages for my friends but also in multiple different projects of greater complexity. I'm also a heavy user of Docker. The problem I came across is that NGINX and Docker sometimes don't go hand to hand.

Many cloud platforms like Google Cloud Run or Heroku, which can run your apps as Docker containers, require your app to listen to a port that is dynamically set via a PORT environment variable.

Although NGINX doesn't support environment variables in its config, we can achieve the same result by using envsubst to substitute the values of environment variables. With envsubst we can replace ${VARIABLE} with corresponding env values.

Let's take this simplified NGINX default.conf config. Notice the value for the listen directive.

server {
  listen       ${PORT};
  server_name  localhost;

  root   /usr/share/nginx/html;
  index  index.html;

  location / {
    try_files $uri $uri/ =404;
  }
}

To make it now work with Docker, we need some shell kung-fu.

FROM nginx:alpine

ADD ./nginx/default.conf /etc/nginx/conf.d/default.template

CMD sh -c "envsubst \"`env | awk -F = '{printf \" \\\\$%s\", $1}'`\" < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"

Since we don't want to hardcode the PORT value during the build time, we substitute PORT in the moment of running the container. It might not be the easiest to read, but it is a simple way to dynamically listen to $PORT env with NGINX.

Photo by Manuel Nägeli on Unsplash.