How to use Nginx Docker with Environment Variables

Milhomem
2 min readJun 16, 2021

Two years ago I was automating a lot of things with Docker. I've always enjoyed using Nginx as a proxy for any FCGI server I was managing as it provides robust and complex processing of HTTP requests and can easily proxy it to FCGI. But one thing was always bothering me: having to create a new image for every small variance required for Nginx.

No more! I've then decided to create my own image that supported environment variables out-of-the-box. Why not?! Inspired by The Twelve Factors and everything I do related to DevOps I rely on environment variables. This makes life easier and deployment seamless forcing the application to forget about what environment it is and being portable.

The result is this image milhomem/nginx, and I love to demonstrate its power using simple docker-compose files. I will use real-life examples that I did recently.

To start with, a simple static content server. All I have to do is open port 80 and map my public folder to the traditional /html one:

static-web:
image: milhomem/nginx
ports:
- "80:80"
volumes:
- ${PWD}/public:/usr/share/nginx/html

Nothing special on the above, but any "complex" configuration requires a change of default.conf, or add a different CMD, or even having to copy files to docker while building a new image.

Well, that was before. Now if I want to change the matching hostname I can simply pass the NGINX_HOST environment variable and done:

static-web:
image: milhomem/nginx
ports:
- "80:80"
environment:
NGINX_HOST: '192.168.99.100.xip.io'
volumes:
- ${PWD}/public:/usr/share/nginx/html

Another case where my Fonts were not served through the normal setup because while consuming the static files from another domain I had it blocked by CORS. Instead of hard-coding it or creating a new image, I've replaced the template file in the image and add a new variable ALLOW_ORIGIN that I can change per container configuration.

static-web:
image: milhomem/nginx
environment:
ALLOW_ORIGIN: '*'
volumes:
- ${PWD}/docker/nginx/assets.tpl:/etc/nginx/conf.d/assets.rules.template
- ${PWD}/public:/usr/share/nginx/html

If you are curious about the assets.tpl file is just a location configuration:

# Cache static assets
location ~ \.(ico|png|gif|jpg|jpeg|css|js|eot|ttf|woff|woff2|svg|pdf) {
expires modified 10d;
log_not_found off;
try_files $uri =404;

if ($uri ~* \.(eot|ttf|woff|woff2|svg)$) {
add_header Access-Control-Allow-Origin ${ALLOW_ORIGIN};
}
}

Moving further, my favourite is to enable me to route my HTTP requests to my FCGIs, in this case, a PHP-FPM server. How painful would be to have to write the rewrite and to "align" the path names between the containers? Not with env vars.

static-web:
image: milhomem/nginx:php
environment:
FASTCGI_HOST: "php-fpm-server"
FASTCGI_FILES_ROOT: "/var/www/html/public"
STATIC_FILES_ROOT: "/var/www/html/public"
volumes:
- ${PWD}/public/:/var/www/html/public/
php-fpm-server:
image: php:7.4-fpm
volumes:
- ${PWD}/:/var/www/html/

I recently noticed that the new Nginx 1.19 adopted the exact same approach, but still, mine has some nice common setup for PHP and my intent is that the community could add or request a flavour for any language.

It is much easier when you can compose the containers images without having to keep rebuilding and customising everything.

I hope this image helps you to get quick setups for your web app containers too! Please star, file an issue, or contribute to this open-source project at https://github.com/milhomem/nginx.

m∫m

--

--

Milhomem

Engenheiro viciado em colocar ideias em prática e fazer códigos alcançarem a realidade