I have a docker project using both nginx and let's encrypt with certbot. I'm quite new to docker, and for my nginx image, I'm using the feature that is helping me to use environment variables in nginx configuration.
On a famous tutorial, they use this command to start nginx and reload it automatically
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
The problem is that when I'm using this command instead of the basic one my template is no longer converted to a working nginx conf.
I want to be able to reload nginx but I also want nginx to transform my template in a valid nginx configuration.
How can I achieve that please ?
Here is my docker-compose.yml
version: '3'
services:
db:
image: mysql
environment:
- MYSQL_DATABASE=${DATABASE_NAME}
- MYSQL_USER=${DATABASE_USER}
- MYSQL_PASSWORD=${DATABASE_PASSWORD}
- MYSQL_ROOT_PASSWORD=${DATABASE_ROOT_PASSWORD}
ports:
- "3306:3306"
volumes:
- ./db/data:/var/lib/mysql
adminer:
image: adminer
restart: always
environment:
- ADMINER_DESIGN=lucas-sandery
ports:
- 8080:8080
php-fpm:
build:
context: ./php-fpm
depends_on:
- db
environment:
- APP_ENV=${APP_ENV}
- APP_SECRET=${APP_SECRET}
- DATABASE_URL=mysql://${DATABASE_USER}:${DATABASE_PASSWORD}@db:3306/${DATABASE_NAME}?serverVersion=5.7
volumes:
- ../app:/var/www
node:
image: node:alpine
volumes:
- ../app:/var/www
working_dir: /var/www
command: "/bin/sh -c 'yarn install ; yarn run watch'"
nginx:
image: nginx:alpine
volumes:
- ../app:/var/www
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/templates:/etc/nginx/templates
- ./logs:/var/log
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
depends_on:
- php-fpm
ports:
- "80:80"
- "443:443"
environment:
- APP_DOMAIN=${APP_DOMAIN}
certbot:
image: certbot/certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
And my site.template.conf file
upstream php-upstream {
server php-fpm:9000;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name ${APP_DOMAIN};
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server ipv6only=on;
ssl_certificate /etc/letsencrypt/live/${APP_DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${APP_DOMAIN}/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
server_name ${APP_DOMAIN};
root /var/www/public;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_pass php-upstream;
fastcgi_index index.php;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_read_timeout 600;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
Thanks
You can add a
restart: always
in thedocker-compose.yml
nginx
section to handle service exits by errors, and also if you want to trigger it manually you can issue adocker-compose restart nginx
in shell at the folder you have theyml
file.I don't know if you've intentionally left out of your question sensitive information like
${APP_DOMAIN}
, but if you want to insert these values you can use docker secrets. You can read more about docker secrets here: https://docs.docker.com/engine/swarm/secrets/(Hint: you don't need to use swarm to have secrets, at the end of this link there is a docker-compose example. As long as you start the services with it you don't need swarm).
EDIT
So the issue is you can't substitute environment variables on a nginx conf file. have you seen this: https://github.com/docker-library/docs/tree/master/nginx#using-environment-variables-in-nginx-configuration-new-in-119 ?
I found this information here: https://serverfault.com/a/1022249/80400
If you want to reload nginx at every 6h, why don't you use a
crontab
? You can keep everything as it is and do in the crontab:(I think
docker-compose exec
is the right command instead ofdocker-compose run
).