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 theconfig
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 :)
Top comments (4)
One could also take advantage of the exit code from Docker instead of processing the output for validation.
So the script could be somethings like this
This is a great idea! Thanks
Great read 😊
I wonder if there is a way to check my docker container config without failing because some upstream host cannot be resolved 🤔.
That was a problem I was facing as well when I used this script. In case you or anyone is looking for an answer, maybe those can help
serverfault.com/questions/700894/m...
stackoverflow.com/questions/328456...