Substitute environment variables in NGINX config from docker-compose

You can avoid some of the hassles with Compose interpreting environment variables by defining your own entrypoint. See this simple example:

  • entrypoint.sh (make sure this file is executable)
#!/bin/sh

export NGINXPROXY

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

exec "$@"
  • 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;"]

My config file has the same content as your nginx.conf, aside from the fact that I had to comment the lines using the Perl module.

Note that I had to mount my config file to another location before I could envsubst it. I encountered some strange behaviour in the form that the file ends up empty after the substitution, which can be avoided by this approach. It shouldn't be a problem in your specific case, because you already embed it in your image on build time.


EDIT

For completeness, to change your setup as little as possible, you just have to make sure that you export your environment variable. Adapt your command like this:

command: ["/bin/bash", "-c", "export NGINXPROXY && envsubst '$$NGINXPROXY' < /etc/nginx/nginx.conf > /etc/nginx/nginx.conf && nginx -g 'daemon off;'"]

...and you should be good to go. I would always recommend the "cleaner" way with defining your own entrypoint, though.


Since nginx 1.19 you can now use environment variables in your configuration with docker-compose. I used the following setup:

# 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
        

I'm going off script a little from the example in the documentation. Note the extra .conf extension on the template file - this is not a typo. In the docs for the nginx image it is suggested to name the file, for example, default.conf.template. Upon startup, a script will take that file, substitute the environment variables, and then output the file to /etc/nginx/conf.d/ with the original file name, dropping the .template suffix.

By default that suffix is .template, but this breaks syntax highlighting unless you configure your editor. Instead, I specified .conf as the template suffix. If you only name your file default.conf the result will be a file named /etc/nginx/conf.d/default and your site won't be served as expected.