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.