Running NGINX with Docker with Let’s Encrypt certificates outside of the container
In this post I want to explain briefly how I solved the problem to run NGINX with docker but keep the let’s encrypt certificates outside of the Docker image. Some approaches include the certificates into the container during the build, i.e. they are generated in the docker image. I wanted to decouple certificates and NGINX. Here’s my approach.
It assumes you have docker
and certbot
(Let’s Encrypt) already installed.
1. Get the certificates
Just generate your certificates like in every let’s encrypt tutorial. $ sudo certbot certonly --standalone --preferred-challenges http -d mydomain.tld -d www.mydomain.tld
2. Let NGINX in Docker container access the certificates
The nginx.conf
inside the NGINX container expects the certificates as usual in /etc/letsencrypt/live/mmydomain.tld/
(path inside container, not inside host system!). In docker-compose.yml
we make sure to have the following volumes configured:
volumes: # for error.log (choose any volume path you want) - .my_docker_compose_volume/nginx:/var/log/nginx # nginx.conf expects ssl files here - /etc/letsencrypt/live/:/etc/letsencrypt/live - /etc/letsencrypt/archive:/etc/letsencrypt/archive # DH params (needs to be generated first, see e.g.: `openssl dhparam -out /etc/ssl/dhparam.pem 2048` - /etc/ssl/:/etc/ssl
That’s it.
3. Example configuration files
docker-compose.yml
version: '3.7' services: # main nginx : reverse proxy for ssl nginx: restart: always container_name: nginx image: phip1611/nginx:latest ports: - 80:80 - 443:443 volumes: - .docker_compose_volume/nginx:/var/log/nginx # Volumes we need for TLS - /etc/ssl:/etc/ssl # dhparams file - /etc/letsencrypt/live:/etc/letsencrypt/live # current certificate - /etc/letsencrypt/archive:/etc/letsencrypt/archive # all certificates (symlinks from /live points here)
nginx.conf (only SSL part)
worker_processes auto; # to get access to additional modules from "nginx-extra" package include /etc/nginx/modules-enabled/*.conf; events { worker_connections 1024; } http { gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css text/xml application/javascript application/json application/xml application/rss+xml image/svg+xml; # neccessary for many server{}-blocks server_names_hash_bucket_size 64; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; more_clear_headers 'server'; # Common TLS Config ssl_certificate /etc/letsencrypt/live/mydomain.tld/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mydomain.tld/privkey.pem; ssl_dhparam /etc/ssl/dhparam.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_ciphers "EECDH-AESGCM:EDH+ESGCM:AES256+EECDH:AES256+EDH"; ssl_prefer_server_ciphers on; add_header Strict-Transport-Security "max-age=31557600; includeSubdomains" always; server { listen 80 default_server; listen [::]:80 default_server; return 301 https://$host$request_uri; } server { server_name mydomain.tld; listen 443 ssl http2; listen [::]:443 ssl http2; location / { proxy_pass http://some-service-running-inside-docker:8080; # container needs to know it doesn't run on "http://some-service-running-inside-docker" proxy_set_header 'X-Forwarded-Host' mydomain.tld; proxy_set_header 'X-Forwarded-Proto' https; proxy_set_header 'X-Forwarded-For' $remote_addr; proxy_set_header 'X-Forwarded-IP' $remote_addr; } } }
Dockerfile (to build nginx)
FROM nginx:1.17.5 # to get nginx_more_headers RUN apt-get update && apt-get install -y nginx-extras RUN rm /etc/nginx/conf.d/default.conf COPY nginx.conf /etc/nginx VOLUME /var/log/nginx
Any more questions? Feel free to ask!
0 Comments