1)To achieve the above, first we need to install docker. Please follow the below link to install docker.
https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository

2) Create a sample application. Create a directory called “helloapp”. Create file index.js.
mkdir helloapp
cd helloapp
vi index.js


3) Copy and paste the below content.

const express = require(“express”);
const app = express();
app.get(“/”, (req, res) => {
res.send(“Hi Everyone ! Welcome to Pheonix Solutions”);
});
app.listen(8080, () => {
console.log(“Server started on port 8080”);
});

4) Create a file with name package.json
vi package.json

5) Copy and paste the below content.

{

“dependencies”: {

“express”: “*”

},

“scripts”: {

“start”: “node index.js”

}
}

6) Now create a Docker file. Dockerfile contains instructions for building a Node application using the Docker node:alpine image and the contents of your current project directory.
vi Dockerfile

7) Now copy and paste the below content. These instructions build a Node image by copying the project code from the current directory to the container and installing dependencies with npm install. They also take advantage of Docker’s caching and image layering by separating the copy of package.json and package-lock.json, containing the project’s listed dependencies, from the copy of the rest of the application code.

#base image
FROM node:alpine


#install dependancies
WORKDIR /usr/helloapp
COPY ./package.json ./
RUN npm install
COPY ./ ./


EXPOSE 8080
#start-up command
CMD [“npm”, “start”]

8) Create a directory in the current project directory for the configuration file
mkdir nginx-conf
nano nginx-conf/nginx.conf

server {
listen 80;
listen [::]:80;


root /var/www/html;
index index.html index.htm index.nginx-debian.html;


server_name dockertestings.pheonixsolutions.com www.dockertestings.pheonixsolutions.com;


location / {
proxy_pass http://dockertestings.pheonixsolutions.com:8080;
}


location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
}

9) Next we will create a docker-compose file. The docker-compose.yml file will define our services, including the Node application and web server. It will specify details like named volumes, which will be critical to sharing SSL credentials between containers, as well as network and port information. It will also allow us to specify specific commands to run when our containers are created. This file is the central resource that will define how our services will work together.
nano docker-compose.yml

Copy and paste the below content.

version: ‘3’
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: helloapp
container_name: helloapp

ports:
– “8080:8080”
restart: always
networks:
– app-network
webserver:
image: nginx:mainline-alpine
container_name: webserver
restart: always
ports:
– “80:80”
volumes:
– web-root:/var/www/html
– ./nginx-conf:/etc/nginx/conf.d
– certbot-etc:/etc/letsencrypt
– certbot-var:/var/lib/letsencrypt
depends_on:
– nodejs
networks:
– app-network
certbot:
image: certbot/certbot
container_name: certbot
volumes:
– certbot-etc:/etc/letsencrypt
– certbot-var:/var/lib/letsencrypt
– web-root:/var/www/html
depends_on:
– webserver
command: certonly –webroot –webroot-path=/var/www/html –email abc@example.com –agree-tos –no-eff-email –staging -d example.com -d www.example.com
volumes:
certbot-etc:
certbot-var:
web-root:
driver: local
driver_opts:
type: none
device: /home/helloapp/

o: bind
networks:
app-network:
driver: bridge

10) We can start our containers with docker-compose up, which will create and run our containers and services in the order we have specified. If our domain requests are successful, we will see the correct exit status in our output and the right certificates mounted in the /etc/letsencrypt/live folder on the webserver container.

First build the image with the below command.
Docker build -t helloapp .

Now run the below command to create the services and run the containers.
docker-compose up -d

11) Using docker-compose ps, check the status of your services.

12) If you want to check the service logs, execute the below command.
docker-compose logs service_name

13) You can now check that your credentials have been mounted to the webserver container with docker-compose exec
docker-compose exec webserver ls -la /etc/letsencrypt/live

14) Now that you know your request will be successful, you can edit the certbot service definition to remove the –staging flag. Open docker-compose.yml
nano docker.compose.yml

15) Find the section of the file with the certbot service definition, and replace the –staging flag in the command option with the –force-renewal flag, which will tell Certbot that you want to request a new certificate with the same domains as an existing certificate. The certbot service definition should now look like below.

certbot:
image: certbot/certbot
container_name: certbot
volumes:
– certbot-etc:/etc/letsencrypt
– certbot-var:/var/lib/letsencrypt
– web-root:/var/www/html
depends_on:
– webserver
command: certonly –webroot –webroot-path=/var/www/html –email abc@gmail.com –agree-tos –no-eff-email –force-renewal -d dockertestings.pheonixsolutions.com

16) You can now run docker-compose up to recreate the certbot container and its relevant volumes. We will also include the –no-deps option to tell Compose that it can skip starting the webserver service, since it is already running.
docker-compose up –force-recreate –no-deps certbot

17) You will see output indicating that your certificate request was successful.

18) Now we will modify the webserver Configuration and Service Definition. First stop the webserver with the below command. Enabling SSL in our Nginx configuration will involve adding an HTTP redirect to HTTPS and specifying our SSL certificate and key locations. It will also involve specifying our Diffie-Hellman group, which we will use for perfect forward secrecy.
docker-compose stop webserver

19) Next, create a directory in your current project directory for your Diffie-Hellman key
mkdir dhparam

20) Generate your key with the openssl command
sudo openssl dhparam -out /home/helloapp/dhparam/dhparam-2048.pem 2048

It will take a few moments to generate the key.

21) To add the relevant Diffie-Hellman and SSL information to your Nginx configuration, first remove the Nginx configuration file you created earlier.
rm nginx-conf/nginx.conf

22) Again create config file.
nano nginx-conf/nginx.conf

23) Add the following code to the file to redirect HTTP to HTTPS and to add SSL credentials, protocols, and security headers.

server {
listen 80;
listen [::]:80;
server_name dockertestings.pheonixsolutions.com;


location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { rewrite ^ https://$host$request_uri? permanent; }
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name dockertestings.pheonixsolutions.com;

server_tokens off;

ssl_certificate /etc/letsencrypt/live/dockertestings.pheonixsolutions.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dockertestings.pheonixsolutions.com/privkey.pem;
ssl_buffer_size 8k;

ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

ssl_protocols TLSv1.2 TLSv1.1 TLSv1;

ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

ssl_ecdh_curve secp384r1;

ssl_session_tickets off;

ssl_stapling on; ssl_stapling_verify on;

resolver 8.8.8.8;

location /
{ try_files $uri @nodejs;
}

location @nodejs {
proxy_pass http://dockertestings.pheonixsolutions.com:8080;
add_header X-Frame-Options “SAMEORIGIN” always;
add_header X-XSS-Protection “1; mode=block” always;
add_header X-Content-Type-Options “nosniff” always;
add_header Referrer-Policy “no-referrer-when-downgrade” always;
add_header Content-Security-Policy “default-src * data: ‘unsafe-eval’ ‘unsafe-inline'” always;
#add_header Strict-Transport-Security “max-age=31536000; includeSubDomains; preload” always;
# enable strict transport security only if you understand the implications
}
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
}

24) Before recreating the webserver service, you will need to add a few things to the service definition in your docker-compose.yml file, including relevant port information for HTTPS and a Diffie-Hellman volume definition.
nano docker-compose.yml

25) In the webserver service definition, add the following port mapping and the dhparam named volume. It will be like below.

webserver:
image: nginx:mainline-alpine
container_name: webserver
restart: always
ports:
– “80:80”
– “443:443”
volumes:
– web-root:/var/www/html
– ./nginx-conf:/etc/nginx/conf.d
– certbot-etc:/etc/letsencrypt
– certbot-var:/var/lib/letsencrypt
– dhparam:/etc/ssl/certs
depends_on:
– nodejs
networks:
– app-network

Next, add the dhparam volume to your volumes definitions

volumes:
certbot-etc:
certbot-var:
web-root:
dhparam:
driver: local
driver_opts:
type: none
device: /root/helloapp/dhparam/
o: bind

Now the complete docker-compose.yml file look like below.

version: ‘3’


services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: helloapp
container_name: helloapp
ports:
– “8080:8080”
restart: always
networks:
– app-network


webserver:
image: nginx:mainline-alpine
container_name: webserver
restart: always
ports:
– “80:80”
– “443:443”
volumes:
– web-root:/var/www/html
– ./nginx-conf:/etc/nginx/conf.d
– certbot-etc:/etc/letsencrypt
– certbot-var:/var/lib/letsencrypt
– dhparam:/etc/ssl/certs
depends_on:
– nodejs
networks:
– app-network


certbot:
image: certbot/certbot
container_name: certbot
volumes:
– certbot-etc:/etc/letsencrypt
– certbot-var:/var/lib/letsencrypt
– web-root:/var/www/html
depends_on:
– webserver
command: certonly –webroot –webroot-path=/var/www/html –email abc@gmail.com –agree-tos –no-eff-email –force-renewal -d dockertestings.pheonixsolutions.com


volumes:
certbot-etc:
certbot-var:
web-root:
dhparam:
driver: local
driver_opts:
type: none
device: /root/helloapp/dhparam/
o: bind


networks:
app-network:
driver: bridge

26) Recreate the webserver service with the below command
docker-compose up -d –force-recreate –no-deps webserver

27) Check your services with docker-compose ps. It should look like below.

28) Finally, you can visit your domain to ensure that everything is working as expected. Navigate your browser to https://example.com. Replace with your own domain and check.

It should look like below.

Leave a Reply