I am trying to create a Dockerfile to set up Let's Encrypt. My rudimentary Docker Compose project contains the following three files:
- test/docker-compose.yml
- test/nginx/Dockerfile
- test/letsencrypt/Dockerfile
Let's Encrypt needs to do two things: (1) an initial install of website certificates upon verification of domain ownership, and (2) a periodic renewal of certificates every 60-90 days using a cron job. The initial install of certificates is an ideal use case for Dockerfile's RUN command since it only occurs once at setup, while the periodic cert renewal is ideal for Dockerfile's ENTRYPOINT command because it needs to run persistently.
However, if I include the full "RUN certbot certonly -d example.com ..." command in the Dockerfile, it fails to build because Let's Encrypt's Certbot application requires a running web server in order to verify the validity of the domain name. What I would like to do to solve this problem is call "RUN certbot --help" during build, and then call "RUN certbot certonly -d example.com ..." at runtime after NGINX has started.
My Docker Compose file is organized as follows:
services:
nginx:
...
letsencrypt:
...
environment:
CERTBOT_PARAMETERS: 'certonly -d example.com ...'
depends_on:
- nginx
And my Let's Encrypt dockerfile is:
FROM ubuntu:bionic
ENV CERTBOT_PARAMETERS="--help"
...
# Install Certs
RUN certbot $CERTBOT_PARAMETERS
...
# Renew Certs
RUN apt-get -y install cron && \
printf "30 */12 * * * root certbot renew > /proc/1/fd/1 2>/proc/1/fd/2\n" > /etc/cron.d/certbot && \
chmod 644 /etc/cron.d/certbot && \
crontab /etc/cron.d/certbot
ENTRYPOINT ["cron", "-f"]
This successfully builds, but when I call "docker-compose up -d" everything runs but the certs don't get installed. If I call "docker exec -it CONTAINER_NAME /bin/bash" and then run "certbot certonly -d example.com ..." manually inside the docker container, then certs do get installed.
I assume there's a problem with calling my CERTBOT_PARAMETERS environment variable at runtime. Perhaps it cannot accept spaces?
How can I call a different RUN command at run-time than at build-time? Should I be using CMD instead of RUN? If so, is it acceptable for CMD and ENTRYPOINT to be called in different stages in the Dockerfile?