SSL certificate for Docker web-app

In this article, I want to share with you how to create an SSL certificate for your web application running on Docker, because. in the Russian-speaking part of the Internet - I did not find such a solution.

SSL certificate for Docker web-app

More details under the cut.

We had docker v.17.05, docker-compose v.1.21, Ubuntu Server 18, and a pint of pure Let'sEncrypt. Not that it would be necessary to deploy production on Docker. But once you start building Docker, it becomes hard to stop.

So, to begin with, I will give the standard settings - which we had at the dev stage, i.e. without port 443 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 for about 2 hours. All the options there are interesting. But at the current stage of the project, we (the business) needed to quickly and reliably fasten SSL Let'sEnctypt ΠΊ container and nothing more.

First of all, we installed on the server certbot
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 execution, certbot will provide us with 2 TXT records that we need to specify in the DNS settings.

_acme-challenge.stomup.ru TXT {Ρ‚ΠΎΡ‚ΠšΠ»ΡŽΡ‡ΠšΠΎΡ‚ΠΎΡ€Ρ‹ΠΉΠ’Π°ΠΌΠ’Ρ‹Π΄Π°Π»CertBot}


And press enter.

After that, certbot will check for these records in DNS and generate certificates for you.
if you have 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 the Let'sEncrypt certificate for 90 days, but now we need to push it to Docker.

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

Docker-compose.yml example with SSL

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"

Linked? Super - continue:

Now we need to change the config to work with 443 port and SSL generally:

Example main.conf config with SSL

#
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 check the performance of SSL. Everything should fly.

Most importantly, do not forget that the Let'sEnctypt certificate is issued for 90 days and you will need to renew it through the command sudo certbot renew, and then restart the project with the command docker-compose restart

As an option, add this sequence to crontab.

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

PS Please take into account that all the scripts presented in the text are not final, now the project is at the stage of deep Dev, so I want to ask you not to criticize the configs - they will be modified many more times.

Source: habr.com

Add a comment