Validate your Nginx configuration files easily with Docker
Tags: docker, nginx, devops
Published: 2018-04-14 12:15:33

---
title: Validate your Nginx configuration files easily with Docker
published: true
description: Create a bash script to validate your nginx config files from anywhere
tags: #docker,#nginx,#devops
---

*This is my first post, please be indulgent and let me know if anything could be improved.*

#Situation

Let's suppose you have your web servers running any version of Nginx, and you are set up for automatic deployment of the Nginx config files (through Jenkins, StriderCD, TeamCity, Travis CI, Strider CD, or any other CICD tool you like) from a Git repository or any other source.

With that setup, everything runs smoothly until someone pushes a modification to the config files that has typos or errors in it, in which case you don't want these files to ever get to the Nginx servers.

To avoid such a situation, you'd want your validations to occur as soon as possible in the update process.

This happened to us a few times, so I decided to write a small script that would validate the `nginx.conf` files prior to allowing the deployment.

#First steps

The first thing we wanted to do was to be able to validate the Nginx config files from a server with Nginx.  That was pretty easy to do with this command:
`nginx -c /etc/nginx/nginx.conf -t`

With valid config files, it returns this:
```
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

With invalid config files, it returns something like this:
```
2018/04/13 21:26:15 [emerg] 1#1: unexpected ";" in /etc/nginx/nginx.conf:155
nginx: [emerg] unexpected ";" in /etc/nginx/nginx.conf:155
nginx: configuration file /etc/nginx/nginx.conf test failed
```

#Dockerizing this validation

However, this requires that the person editing the config file had Nginx installed on its machine. This is not always the case, and we didn't want to install Nginx on the build server either (there could be multiple versions on different servers too...), so we turned to Docker as we already use it a lot.

After a few minutes, we were able to come up with a similar command that could run from every system that has Docker installed:

```
docker run --rm -t -a stdout --name my-nginx -v $PWD/config/:/etc/nginx/:ro nginx:latest nginx -c /etc/nginx/nginx.conf -t
```

Docker command explained briefly:
- `--rm` : Removes the container after execution completes
- `-t -a stdout` : Outputs the container logs on the standard output
- `--name my-nginx` : Name of the docker container
- `-v $PWD/config/:/etc/nginx/:ro` : Maps the `config` subfolder to Nginx config folder inside the container
- `nginx:latest` : Nginx image version to use from hub.docker.com
- `nginx -c /etc/nginx/nginx.conf -t` : Nginx command to validate nginx.conf file

*There might be some adjustments required for it to run on Docker for Windows*

This assumes you have the following folder structure:
- ./
- ./config
- ./config/nginx.conf

With that, everyone could run this command in the parent folder of the config directory and see if their `nginx.conf` file is valid or not.

#Making it simpler with a bash script

Though that was already a good start, we wanted to make it so that we get a SUCCESS or a FAILED message, whether the config file was valid or not.  We also wanted to be able to specify a more dynamic version for the Nginx docker image and mostly, didn't want to remember all this command.

Here is what we ended up with in a file called `checkNginx.sh`:
```
#!/bin/bash
rootPath=$1
nginxVersion=1.13  # Could also be passed as an argument using $2

result=$(docker run --rm -t -a stdout --name my-nginx -v ${rootPath}/config/:/etc/nginx/:ro nginx:$nginxVersion nginx -c /etc/nginx/nginx.conf -t)

# Look for the word successful and count the lines that have it
# This validation could be improved if needed
successful=$(echo $result | grep successful | wc -l)

if [ $successful = 0 ]; then
    echo FAILED
    echo "$result"
    exit 1
else
    echo SUCCESS
fi
```

This script can be called using the following command: 
`bash checkNginx.sh $PWD`

It outputs `SUCCESS` if everything is ok or the following if there is an error:

```
FAILED
2018/04/13 21:26:15 [emerg] 1#1: unexpected ";" in /etc/nginx/nginx.conf:155
nginx: [emerg] unexpected ";" in /etc/nginx/nginx.conf:155
nginx: configuration file /etc/nginx/nginx.conf test failed
```

Then we were able to run this same command from the build server, at the Test phase of the deployment process and abort the deployment of the configs completely when a Nginx config file had a typo or an error in it.

This could also have been added to a *pre-commit* or *pre-push* Git hook for the repository keeping track of these configs, but so far we didn't feel the need to do so.

Thanks for reading, hope you appreciated :)