How to use docker to generate wildcard SSL certificates for your website?

Google Chrome has started giving a warning for a non-SSL website and hence it has become more important than ever to generate SSL certificate for your website today!

When it comes to “docker” idea is simple, you mount a volume to share certificates with other containers. There are many docker images which have ‘in-built’ SSL generator. However, if you want it to be scalable, then this is a pretty bad way to do it. You would want to keep a track of all subdomains and their certificates along with where they have been generated. Load-balancers need not to be pointing to the “right” container during validation. So problems are many.

Docker image

I am using adferrand/letsencrypt-dns for this and it comes with ‘auto-restarting’ a docker container if a matching certificate has been renewed. It supports for 50+ dns managers and I am sure yours is covered ­čśë . I am a fan of Linode, if you are serious about your business growth, give them a shot.
Docker Compose content:

cat docker-compose.yml

version: '3.2'
services:
  letsencrypt-dns:
    image: adferrand/letsencrypt-dns
    restart: always
    volumes:
        - "/etc/passwd:/etc/passwd:ro"
        - "/etc/group:/etc/group:ro"
        - "/var/run/docker.sock:/var/run/docker.sock"
        - "./letsencrypt:/etc/letsencrypt"
    environment:
        - CERTS_USER_OWNER=
        - CERTS_GROUP_OWNER=
        - CERTS_DIRS_MODE=0755
        - CERTS_FILES_MODE=0644
        - LETSENCRYPT_USER_MAIL=@.com
        - LEXICON_SLEEP_TIME=1500
        - LEXICON_PROVIDER=linode
        - LEXICON_LINODE_TOKEN=

Explaining the docker-compose.yml

We are mounting passwd and group as read-only to enable host user and group respectively.

Adding docker.sock ensures that it can restart related docker containers OR execute a command inside the targetted container. If you don’t mount it, containers will have old certificates even after certificates have been renewed and thus, it is very important that you mount it.

Since, dns server is using Linode’s DNS manager, we are adding LEXICON for linode and token. Sleep timing is 1500 seconds that means 25 mins, making each domain to be validated after 25 mins of adding the verification code in dns. If you are in USA, it will probably work with much lesser like 500 seconds.

Example content of domains.conf


cat letsencrypt/domains.conf

webapplicationconsultant.com *.webapplicationconsultant.com autorestart-containers=nginx_nginx_1,nginx_nginx_2
varunbatra.com *.varunbatra.com autocmd-containers=varunbatra_static_1:service nginx reload
  1. webapplicationconsultant.com *.webapplicationconsultant.com autorestart-containers=nginx_nginx_1,nginx_nginx_2 will restart containers by the name nginx_nginx_1 and nginx_nginx_2 once certificates of webapplicationconsultant.com has been renewed
  2. varunbatra.com *.varunbatra.com autocmd-containers=varunbatra_static_1:service nginx reload will execute the command service nginx reload once certificates of varunbatra.com have been renewed.

Generated SSL locations

  1. ./letsencrypt/live/varunbatra.com/fullchain.pem
  2. ./letsencrypt/live/webapplicationconsultant.com/fullchain.pem

Now you can use these certificates in NGINX or APACHE or ‘Whatever’ ­čÖé Just make sure whatever you do, you don’t forget to add a proper autorestart and autocmd lines for their respective containers.

Worth Sharing?

How to prepare docker for a production?

In order to use Docker on Production, you have to ensure that you can deploy easily, maintain multiple similar services and be ‘reboot proot’

1. Ditch Docker – Pick Compose

Docker compose is a great tool to keep docker as a configuration. You can add multiple dockers that too interlinked in docker-compose.yml file and run it.

2. Reboot proof Containers

There will be unavoidable circumstances when your host provider will reboot your system for scheduled or emergency maintenance. To ensure that containers/services come back online – use a ‘restart’ option. Version 2 and above support restart option.

[code]
version: '3.2'
services:
  web:
    image: nginx
    restart: always
[/code]

3. Avoiding network_mode: hosts

Network mode (network_mode) host ignores the port binding. Whatever port is exposed by the container is exposed from host machine. With multiple containers in a single machine, it is very commanded to have few services with same type – example Nginx┬áserving static files when using docker on production. For this reason, only the first service will be able to start and rest will give port already used error. Thus, avoiding network_mode has hosts should be avoided unless it is absolutely required.

4. Log Management

Logs can become overwhelmingly problematic if not managed. Ensure the format of the log, its location and also check for logrotate service.  An unchecked log file will choke your server. It can disable ssh logins which can be devastating.

[code]
logging:
  options:
    max-size: '12m'
    max-file: '5'
  driver: json-file
[/code]

5. Not everything deserves a Container

It is tempting to have a stateless or portable container. However, some services need a lot of IO read-write and such services are often relying on databases. There can be a huge performance difference when these databases are not in containers.

 

Worth Sharing?

How to truncate docker logs?

Docker logs are organized inside their respective container folders. However, with a single command you can truncate all the docker logs as following:

[code lang="bash"]sudo truncate -s 0 /var/lib/docker/containers/*/*-json.log[/code]

Worth Sharing?