SSL certificate for Docker web app

In this article, I want to share with you a way to create an SSL certificate for your web application running on Docker, as I couldn't find a similar solution in the Russian-speaking part of the internet.

SSL certificate for Docker web app

Read more below.

We had Docker v.17.05, Docker Compose v.1.21, Ubuntu Server 18, and a clean Let’s Encrypt setup. It’s not necessarily required to run production on Docker, but once you start getting into Docker, it becomes hard to stop.

So to begin with, I will provide the standard settings we had during 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 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. To be honest, I studied the .com zone for about 2 hours. All the suggested options there are interesting, but at the current stage of the project, we (the business) needed to quickly and reliably implement SSL Let’sEncrypt to nginx for the 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 executing certbot, it will provide us with 2 TXT records that need to be specified in the DNS settings.

_acme-challenge.stomup.ru TXT {theKeyThatCertBotGaveYou}


And press enter.

After that, certbot will check for these records in DNS and create certificates for you.
if you added the certificate, but certbot couldn't find it — try running the command again in 5-10 minutes..

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

To do this, we simply link the directories in the docker-compose.yml file under the nginx section.

Example docker-compose.yml 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? Great — let's continue:

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

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;
	}
}

So after these manipulations, we go to the directory with Docker-compose, type docker-compose up -d. And check the SSL functionality. Everything should be up and running.

Just don't forget that the Let’sEncrypt certificate is issued for 90 days, and you will need to renew it using 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 simplest way to connect SSL to a Docker Web app.

P.S. Please note that all scripts presented in the text are not final; the project is currently in deep development, so I ask you not to criticize the configs — they will change many times.

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster