5/5 - (1 vote)

In this article I want to share with you how to create an SSL certificate for your Docker web application.

So, for starters, I’ll give you the standard settings – which we had at the dev stage, i.e. without 443 ports and SSL in general:

  • docker-compose.yml
version: '2'
services:
    php:
        build: ./php-fpm
        volumes:
            - ./StomUp:/var/www/StomUp
            - ./php-fpm/php.ini:/usr/local/etc/php/php.ini
        depends_on:
            - mysql
        container_name: "StomPHP"
    web:
        image: nginx:latest
        ports:
            - "80:80"
            - "443:443"
        volumes:
            - ./StomUp:/var/www/StomUp
            - ./nginx/main.conf:/etc/nginx/conf.d/default.conf
        depends_on:
            - php
    mysql:
        image: mysql:5.7
        command: mysqld --sql_mode=""
        environment:
            MYSQL_ROOT_PASSWORD: xxx
        ports:
            - "3333:3306"

 

  • nginx / main.conf
 server {
    listen 80;
    server_name *.stomup.ru stomup.ru;
   root /var/www/StomUp/public;
     client_max_body_size 5M;

    location / {
        # try to serve file directly, fallback to index.php
        try_files $uri /index.php$is_args$args;
  }

    location ~ ^/index\.php(/|$) {
      #fastcgi_pass unix:/var/run/php7.2-fpm.sock;
       fastcgi_pass php:9000;
       fastcgi_split_path_info ^(.+\.php)(/.*)$;
      include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
       fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_buffer_size 128k;
       fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;
       internal;
    }

    location ~ \.php$ {
        return 404;
    }

     error_log /var/log/nginx/project_error.log;
    access_log /var/log/nginx/project_access.log;
}

Next, we actually need to implement SSL. Honestly – I studied the com zone around 2 hours. All the proposed options there are interesting. But at the current stage of the project, we (the business) needed to quickly and reliably fasten SSL Let’sEnctypt to the nginx container and nothing more.

First of all, we installed certbot on the server

sudo apt-get install certbot

Next, we generated wildcard certificates for our domain

sudo certbot certonly -d stomup.ru -d *.stomup.ru --manual --preferred-challenges dns

after running certbot will provide us with 2 TXT records that need to be specified in the DNS settings.

_acme-challenge.stomup.ru TXT {тотКлючКоторыйВамВыдалCertBot}

And press enter.

After that, certbot will check the availability of these records in DNS and create certificates for you.

If you added a certificate, but certbot did not find it, try restarting the command after 5-10 minutes.

Well, here we are the proud owners of Let’sEncrypt certificate for 90 days, but now we need to send it to Docker.

To do this, in the most banal way in docker-compose.yml, in the nginx section – link directories.

version: '2'
services:
    php:
        build: ./php-fpm
        volumes:
            - ./StomUp:/var/www/StomUp
            - /etc/letsencrypt/live/stomup.ru/:/etc/letsencrypt/live/stomup.ru/
            - ./php-fpm/php.ini:/usr/local/etc/php/php.ini
        depends_on:
            - mysql
        container_name: "StomPHP"
    web:
        image: nginx:latest
        ports:
            - "80:80"
            - "443:443"
        volumes:
            - ./StomUp:/var/www/StomUp
            - /etc/letsencrypt/:/etc/letsencrypt/
            - ./nginx/main.conf:/etc/nginx/conf.d/default.conf
        depends_on:
            - php
    mysql:
        image: mysql:5.7
        command: mysqld --sql_mode=""
        environment:
            MYSQL_ROOT_PASSWORD: xxx
        ports:
            - "3333:3306"

Have you linked? Super – continue:

Now we need to change the nginx config to work with port 443 and SSL in general:

#
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;

	server_name *.stomup.ru stomup.ru;
	set $base /var/www/StomUp;
	root $base/public;

	# SSL
	ssl_certificate /etc/letsencrypt/live/stomup.ru/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/stomup.ru/privkey.pem;
	ssl_trusted_certificate /etc/letsencrypt/live/stomup.ru/chain.pem;

      client_max_body_size 5M;

      location / {
          # try to serve file directly, fallback to index.php
          try_files $uri /index.php$is_args$args;
      }

      location ~ ^/index\.php(/|$) {
          #fastcgi_pass unix:/var/run/php7.2-fpm.sock;
          fastcgi_pass php:9000;
          fastcgi_split_path_info ^(.+\.php)(/.*)$;
          include fastcgi_params;
          fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
          fastcgi_param DOCUMENT_ROOT $realpath_root;
          fastcgi_buffer_size 128k;
          fastcgi_buffers 4 256k;
          fastcgi_busy_buffers_size 256k;
          internal;
      }

      location ~ \.php$ {
          return 404;
      }

      error_log /var/log/nginx/project_error.log;
      access_log /var/log/nginx/project_access.log;
}


# HTTP redirect
server {
	listen 80;
	listen [::]:80;

	server_name *.stomup.ru stomup.ru;

	location / {
		return 301 https://stomup.ru$request_uri;
	}
}

Actually after these manipulations – we go to the directory with Docker-compose, write docker-compose up -d. And we check the functionality of SSL. Everything should work.

The main thing is not to forget that Let’sEnctypt certificate is issued for 90 days and you will need to update it through the sudo certbot renew command, and then restart the project with the docker-compose restart command

Alternatively, add this sequence to crontab.

In my opinion, this is the easiest way to connect SSL to the Docker Web-app.

P.S. I ask you to take into account that all the scripts presented in the text are not final, now the project is at the deep Dev stage, so I want to ask you not to criticize the config files – they will be modified many more times.