How to fix unsecure connection in local environment with docker and docker-compose

Do you need to run a site locally over https, but don’t know how to do it over a secure connection? Find out how to do this in this article.

At first, create the below structure in a folder:

my-project
-- docker-compose.yml
-- nginx (folder)
---- Dockerfile
---- default.conf
---- mydomain.local.ext
-- index.php

Add the code below to the docker-compose.yml file.

version: "3"services:
nginx:
build: ./nginx
container_name: nginx
ports:
- 80:80
- 443:443
volumes:
- $PWD/nginx/default.conf:/etc/nginx/conf.d/default.conf
- $PWD:/usr/share/nginx/html
- ssl:/etc/ssl
php:
image: php:7.1-fpm
container_name: php
volumes:
- $PWD:/var/www/html
volumes:
ssl:

Add the code below to the nginx/Dockerfile file.

FROM nginx:1.12
ADD ./mydomain.local.ext /etc/ssl/mydomain.local.ext
RUN apt-get update \
&& apt-get install -y openssl \
&& NAME=mydomain.local \
&& openssl genrsa -out /etc/ssl/myCA.key 2048 \
&& openssl req -x509 -new -nodes -key /etc/ssl/myCA.key -sha256 -days 3650 -out /etc/ssl/myCA.pem \
-subj "/C=PT/ST=Lisbon/L=Lisbon/O=MyCompany/OU=IT Department/CN=$NAME" \
&& openssl genrsa -out /etc/ssl/$NAME.key 2048 \
&& openssl req -new -key /etc/ssl/$NAME.key -out /etc/ssl/$NAME.csr \
-subj "/C=PT/ST=Lisbon/L=Lisbon/O=MyCompany/OU=IT Department/CN=$NAME" \
&& openssl x509 -req -in /etc/ssl/$NAME.csr -CA /etc/ssl/myCA.pem -CAkey /etc/ssl/myCA.key -CAcreateserial \
-out /etc/ssl/$NAME.crt -days 3650 -sha256 -extfile /etc/ssl/$NAME.ext

PS: mydomain.local must be the domain that you want to use.

Add the code below to nginx/mydomain.local.ext file.

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = mydomain.local

PS: mydomain.local must be the domain that you want to use.

Add the code below to nginx/default.conf file.

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name mydomain.local;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
ssl on;
ssl_certificate /etc/ssl/mydomain.local.crt;
ssl_certificate_key /etc/ssl/mydomain.local.key;
server_name mydomain.local;access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
root /usr/share/nginx/html;
index index.php index.html index.htm;
try_files $uri $uri/ /index.php?$uri&$args;
}
#error_page 404 /404.html;# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
root /var/www/html;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SERVER_NAME $http_host;
include fastcgi_params;
}
}

PS: mydomain.local must be the domain that you want to use.

Add the Hello World program to the index.php file.

<?php echo 'Hello World'; ?>

Run the containers in the background with the command below:

docker-compose up -d

Now, you can access https://mydomain.local in your browser. Don’t forget to add mydomain.local to you hosts file (/etc/hosts). You will get something like the image below.

You can click on the Advanced button and then on the Proceed to mydomain.local (unsafe) link. However, you will continue to receive Your connection to this site is not secure.

To solve it, just copy the Certificate Authority from the container and add it to your to your browser. To copy the Certificate Authority, run the command below (I’ll copy it to ~/Downloads folder, but you can choose another one):

docker cp nginx:/etc/ssl/myCA.pem ~/Downloads/myCA.pem

How to import Certificate Authority in Google Chrome

Open it » Click on the three dots » Settings » Privacy and Security » Security » Manage Certificates » Authorities » Import » Choose the copied file » Check all the checkboxes » Click Ok » Close and re-open the Google Chrome.

How to import Certificate Authority in FireFox

Open it » Click on the three dots » Preferences » Privacy and Security » Certificates » View Certificates » Authorities » Import… » Choose the copied file » Check all the checkboxes » Click Ok.

How to use the certificates in other containers

Sometimes you will need to the use certificates in other containers. Doing this is very simple, just add the ssl volume to the respective container. Below I will show you how to do it in a real case (I’ll do it for Mosquitto Broker).

mqtt:
image: eclipse-mosquitto:1.6.12
container_name: mqtt
depends_on:
- nginx
ports:
- 1883:1883
- 1884:1884
volumes:
- ssl:/mosquitto/ssl

This way, you will have the certificates generated by the Nginx container in the MQTT container in the /mosquitto/ssl folder.

You can get the complete code on GitHub https://github.com/luiscoutinh/fix-unsecure-connection

Full Stack Web Developer