Angular, Nginx & Docker: Environment variable substitution in Nginx Configuration file using templates

AngularEnthusiast
JavaScript in Plain English
6 min readApr 25, 2024

--

You will find this story useful, if you wanted to substitute variables in your nginx configuration file at runtime and not hardcode them. Initially, I found this subject really confusing, so I have tried my best to keep this story as simple as possible.

Lets begin !

Below is a very basic nginx configuration file. I have used an environment variable nginxPort in the below file. I will substitute the value of the variable in this file at runtime.

How does the variable substitution happen ?

  1. We will create a template in some folder ,say folder-A. The template is nothing but the nginx configuration file with one/more variables which require substitution with some value.
  2. The nginx docker image has a function which will read this template file and execute the envsubst command on the template file.
  3. The output file produced post executing envsubst command on the template file will be stored in some folder, say folder-B. This output file will be the nginx configuration file, with the variables substituted with appropriate values.

In the above 3 steps, below are 3 parameters you can control using environment variables.

  1. The template file name suffix. The suffix of the template file by default is .template.

NGINX_ENVSUBST_TEMPLATE_SUFFIX is the environment variable to be set, if you want the function in the nginx docker image to read template files with a different suffix.

2. The input folder in which the template file is located. /etc/nginx/templates is the directory which by default contains template files.

NGINX_ENVSUBST_TEMPLATE_DIR is the environment variable to be set, if you want to store the template file in a folder other than /etc/nginx/templates.

3. The output folder in which the output file of envsubst command will be located. By default it is /etc/nginx/conf.d.

NGINX_ENVSUBST_OUTPUT_DIR is the environment variable to be set, if you want to store the output of the envsubst command in a folder other than /etc/nginx/conf.d

So let me summarize the default behavior :

The function in the nginx docker image will read template files only with .template suffix located within the /etc/nginx/templates folder.

Next, it will execute the envsubst command on the template file and the output of the command will be a output file which will be located inside the /etc/nginx/conf.d folder.

The name of the output file will be same as the template file but without the .template extension. For example, if the template filename is mynginxtemp.template, then the output filename will be mynginxtemp

Implementation

I will demonstrate both the default and customized implementation of the substitution.

I. Default Implementation:

Below is the Dockerfile.

Observe the below line in the above file.

COPY nginx/nginx.config /etc/nginx/templates/default.conf.template

We are copying the nginx configuration file i.e nginx.config into a file named default.conf.template. We have used the default .template suffix for the template file. Also the template file is located within the default template folder : /etc/nginx/templates.

docker-compose.yml

I have used Docker Compose for container management in this story. If using Kubernetes, ConfigMaps can be used for setting environment variables.

As you can see above, we have set the environment variable nginxport to a value 80.

Lets now start the “docker compose build”.

C:\Users\User\angular\nginxDemo>docker compose build
[+] Building 77.1s (17/17) FINISHED docker:default
=> [nginx-demo internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 473B 0.0s
=> [nginx-demo internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [nginx-demo internal] load metadata for docker.io/library/node:alpine 3.1s
=> [nginx-demo internal] load metadata for docker.io/library/nginx:alpine 3.9s
=> [nginx-demo node 1/7] FROM docker.io/library/node:alpine@sha256:db8772d9f5796ac4e8c47508038c413ea1478da010568a2e48672f19a8b80cd2 0.0s
=> [nginx-demo stage-1 1/4] FROM docker.io/library/nginx:alpine@sha256:fdbfdaea4fc323f44590e9afeb271da8c345a733bf44c4ad7861201676a95f42 0.0s
=> [nginx-demo internal] load build context 3.8s
=> => transferring context: 2.01MB 3.6s
=> CACHED [nginx-demo node 2/7] WORKDIR /app 0.0s
=> CACHED [nginx-demo node 3/7] COPY package.json package-lock.json ./ 0.0s
=> CACHED [nginx-demo node 4/7] RUN npm cache clean — force 0.0s
=> CACHED [nginx-demo node 5/7] RUN npm install 0.0s
=> [nginx-demo node 6/7] COPY . . 28.3s
=> [nginx-demo node 7/7] RUN npm run build 40.2s
=> CACHED [nginx-demo stage-1 2/4] RUN rm -r /usr/share/nginx/html/* 0.0s
=> CACHED [nginx-demo stage-1 3/4] COPY — from=node /app/dist/nginx-demo /usr/share/nginx/html 0.0s
=> [nginx-demo stage-1 4/4] COPY nginx/nginx.config /etc/nginx/templates/default.conf.template 0.1s
=> [nginx-demo] exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:15ffdd484946775182426025eed69d7cd72c0eacfa99da8416ce015a8d78ed3a 0.0s
=> => naming to docker.io/library/testing-nginx 0.0s

Next, lets bring the service up using the “docker compose up” command.

Lets now move to our docker container file system.

=> Below is the default.conf.template file within the /etc/nginx/templates folder. The content of the default.conf.template will be same as the nginx.config file, because of the below COPY instruction in the Dockerfile.

COPY nginx/nginx.config /etc/nginx/templates/default.conf.template

=> Below is the output of the envsubst command stored in the /etc/nginx/conf.d folder. Observe that the name of the output file is same as the template file but without the .template extension. Also in this file, the environment variable nginxport has been replaced with its value :80.

Successfully accessing the angular application on port 8081.

II. Custom Implementation:

In the custom implementation, we will change the template filename suffix, the location of the template file and the location of the output file.

Updated Dockerfile

2 changes has been done.

=>I have modified the below COPY instruction

FROM

COPY nginx/nginx.config /etc/nginx/templates/default.conf.template

TO

COPY nginx/nginx.config /mynginx/templates/env-nginx.nginxtemplates

From the updated COPY instruction, the template filename is env-nginx.nginxtemplates

The new template file suffix is .nginxtemplates .The template file will be located in a new folder : /mynginx/templates.

You can give any filename, file suffix and folder name. The above are just examples.

=> After the COPY instruction, we have added 2 more instructions to create our custom output folder /mynginx/output and make it writable.

RUN mkdir /mynginx/output
RUN chmod +x /mynginx/output

Updated docker-compose.yml

Observe the 3 additional environment variables added to use a different template file suffix: .nginxtemplates, different folder location for the template file: /mynginx/templates and also a different folder location for the output file: /mynginx/output.

We have discussed these variables in the beginning of the story.

Executing the “docker compose build”.

Executing the “docker compose up” command.

Our docker container is up and running. Lets check the container file system.

As you can see below, the custom /mynginx/templates folder we created to store template file env-nginx.nginxtemplates. The content of this template file is the same as nginx.config.

Post execution of the envsubst command on the template file, the output file is located in the /mynginx/output folder as you see below. The output filename: env-nginx is same as the template filename but without the .nginxtemplates suffix.

Also observe that the nginxport environment variable has been substituted with value 80 in the output file.

In Plain English 🚀

Thank you for being a part of the In Plain English community! Before you go:

--

--

Loves Angular and Node. I wish to target issues that front end developers struggle with the most.