Add SSL (https) using Docker container (cerbot) Let’s Encrypt with Apache or Nginx with your domain or subdomain

Tiempo de lectura: 3 minutos

Reading time: 3 minutes

Continuing with the tutorials on Docker (https://devcodelight.com/category/docker) and building upon the last post Creating a Docker Compose Container with Apache + PHP + MySQL (XAMPP with Docker)

We can add a Docker container that allows us to add SSL using Certbot (https://hub.docker.com/r/certbot/certbot/), which is also compatible with Apache or Nginx (independent container).

This works for your domain or subdomain.

The idea is that this container needs to have an Apache or Nginx service without SSL (HTTP) to perform the initial verification (key exchange to identify the domain). Once the certificates are downloaded, they are stored in a folder that can be linked with Docker Compose.

Starting from (docker-compose.yml):

version: "3"
# Indicate the Docker Compose version we are using
# Then define the services we are going to implement
services:
  contendor_mysql:
    image: mysql:5.7
    container_name: mysql-container
    environment:
        MYSQL_DATABASE: db
          # You can use any username, in this example we use "test"
        MYSQL_USER: test
          # Password for the MySQL user
        MYSQL_PASSWORD: testp
          # Password for root
        MYSQL_ROOT_PASSWORD: root
    volumes:
      # Mount a volume for MySQL to preserve database data
      - ./mysql:/var/lib/mysql
    expose:
      - 3306
    ports:
      - 3306:3306
# Here you can specify the desired name
  mi_servicio_apache:
    # Specify the folder where we store the Dockerfile
    build: 
      context: ./Dockerfile
      # Specify the Dockerfile for this container
      dockerfile: apache_file
    # Remove this line as it is replaced by the dockerfile
    # image: php:7.0-apache
    container_name: apache-container
    volumes:
      # Folder where we store web files: internal folder of Docker
      - ./www/:/var/www/html
    expose:
      # Port we want to expose for sharing with other containers
      - 80
    ports:
      # Port on our machine : Port within Docker (always 80 for Apache or 443 for SSL)
      - 80:80
    links: 
      - contendor_mysql
  contenedor_phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin-container
    ports:
     - 776:80
    links: 
      - contendor_mysql:db

Now let’s add the certbot/certbot container to the file.

  certbot:
    image: certbot/certbot
    container_name: certbot
    volumes:
      - ./certs:/etc/letsencrypt/archive
      - ./www/:/var/www/html
    depends_on:
      - mi_servicio_apache
    command: certonly --webroot --webroot-path=/var/www/html --emailcontact@yourdomain.com --agree-tos --no-eff-email --staging -d yourdomain.com
#command: certonly --webroot --webroot-path=/var/www/html --email contact@yourdomain.com --agree-tos --no-eff-email -d www.yourdomain.com -d yourdomain.com
#command: renew --webroot --webroot-path=/var/www/html --no-self-upgrade

Let’s explain the construction of this image:

  • We use the Certbot image as mentioned earlier:
image: certbot/certbot
  • We mount volumes to access the certificate from outside Docker and access the Apache or Nginx web directory (www) from the certbot container:
volumes:
  - ./certs:/etc/letsencrypt/archive
  - ./www/:/var/www/html
  • We create a dependency with the Apache container so that this container is not created if the Apache container is not ready, as it is needed to download the certificates:
depends_on:
  - mi_servicio_apache

And now there are 3 commands that I have added, two of which are commented out.

Let’s explain what each command does:

  • The first command creates a test certificate (staging) so that the Let’s Encrypt server doesn’t block the certificate generation and we can test it. When we generate this certificate, the browser will warn us that it’s not secure because it’s a test certificate (staging). We pass the parameters –email to indicate our email address where we’ll be notified when the certificates expire, and with the -d parameter we indicate the domain for which we want to generate the certificate. It’s important that this domain points to our machine’s IP address, otherwise, it will give us an error.

command: certonly --webroot --webroot-path=/var/www/html --email contact@yourdomain.com --agree-tos --no-eff-email --staging -d yourdomain.com

  • The next command generates the final certificate (be careful with this, as if we generate it multiple times, it will block us for a few hours before we can generate it again).command: certonly --webroot --webroot-path=/var/www/html --email contact@yourdomain.com --agree-tos --no-eff-email -d www.yourdomain.com -d yourdomain.com
  • And the last command is for renewing the certificate.
    command: renew --webroot --webroot-path=/var/www/html --no-self-upgrade

With all this, we have our Docker Compose container with SSL and compatible with Apache or Nginx.

I’ll leave the code on GitHub for you to download: https://github.com/IsMMA/devcodelight_docker/tree/version_5

Leave a Comment