0
votes

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?

1

1 Answers

1
votes

The RUN command in the Dockerfile will only get executed when the image is built.

The CERTBOT_PARAMETERS environment variable set in your docker-compose file will only be available after the image is built.

I'm not sure how you are building the image but if you want to pass values that are available at build-time, you need to use build arguments, e.g,. if using docker-compose see the docs re ARGS: https://docs.docker.com/compose/compose-file/#args

which are environment variables accessible only during the build process.

Regarding CMD and ENTRYPOINT, you should read up on their use as they are not mutually exclusive, see: https://docs.docker.com/engine/reference/builder/#entrypoint

They control what command the image runs once it starts after the image is built while RUN is only used during the build.