Reputation: 21302
I would like to pass global variables to my nginx app.conf via a app.conf.template file using docker and docker-compose.
When using an app.conf.template file with no commands in docker-compose.yaml
my variables translate successfully and my redirects via nginx work as expected. But when I use a command in docker-compose my nginx and redirects fail.
My set up is per the instructions on the documentation, under section 'Using environment variables in nginx configuration (new in 1.19)':
Out-of-the-box, nginx doesn't support environment variables inside most configuration blocks. But this image has a function, which will extract environment variables before nginx starts.
Here is an example using docker-compose.yml:
web: image: nginx volumes:
- ./templates:/etc/nginx/templates ports:
- "8080:80" environment:
- NGINX_HOST=foobar.com
- NGINX_PORT=80
By default, this function reads template files in /etc/nginx/templates/*.template and outputs the result of executing envsubst to /etc/nginx/conf.d ... more ...
My docker-compose.yaml works when it looks like this:
version: "3.5"
networks:
collabora:
services:
nginx:
image: nginx
depends_on:
- certbot
- collabora
volumes:
- ./data/nginx/templates:/etc/nginx/templates
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
ports:
- "80:80"
- "443:443"
env_file: .env
networks:
- collabora
On host I have a conf file ./data/nginx/templates/app.conf.template
which contains a conf file with global variables throughout in the form ${variable_name}
.
With this set up I'm able to run the container and my redirects work as expected. When I exec
into the container I can cat /etc/nginx/conf.d/app.conf
and see the file with the correct variables swapped in from the .env file.
But I need to add a command to my docker-compose.yaml:
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
When I add that command the set up fails and the global variables are not swapped into the app.conf file within the container.
On another forum it was suggested I move the command
into it's own file in the container. I then gave this a try and created a shell script test.sh
:
#/bin/sh
while :;
do sleep 6h & wait $${!};
nginx -s reload;
done;
My new docker-compose:
version: "3.5"
networks:
collabora:
services:
nginx:
image: nginx
depends_on:
- certbot
- collabora
volumes:
- ./data/nginx/templates:/etc/nginx/templates
- ./test.sh:/docker-entrypoint.d/test.sh # new - added test.sh into the container here
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
ports:
- "80:80"
- "443:443"
env_file: .env
networks:
- collabora
This fails. Although when I exec into the container and cat /etc/nginx/conf.d/app.conf
I DO see the correct config, it just does not seem to be working in that my redirects, which otherwise do work when I don't include this test.sh script within /docker-entrypoint.d/
.
I asked nearly same question yesterday and was given a working solution. However, it 'feels more correct' to add a shell script to the container at /docker-entrypoint.d/
and go that route instead like I've attempted in this post.
Upvotes: 0
Views: 894
Reputation: 312500
For what you're trying to do, I think the best solution is to create a sidecar container, like this:
version: "3.5"
networks:
collabora:
volumes:
shared_run:
services:
nginx:
image: nginx:1.19
volumes:
- "shared_run:/run"
- ./data/nginx/templates:/etc/nginx/templates
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
ports:
- "80:80"
- "443:443"
env_file: .env
networks:
- collabora
nginx_reloader:
image: nginx:1.19
pid: service:nginx
volumes:
- "shared_run:/run"
entrypoint:
- /bin/bash
- -c
command:
- |
while :; do
sleep 60
echo reloading
nginx -s reload
done
This lets you use the upstream nginx
image without needing to muck about with its mechanics. The key here is that (a) we run the nginx_reloader
container in the same PID namespace as the nginx
container itself, and (b) we arrange for the two containers to share a /run
directory so that the nginx -s reload
command can find the pid of the nginx
process in the expected location.
Upvotes: 4