Dockerising my Blog and Publishing on Github Push Webhooks

Docker allows us to package and run applications as an isolated process on a shared operating system, acting as a lighter weight alternative to virtual machines. The reason I chose to dockerise my blog was the same as everybody else, 'speeding up the deploy and delivery of myapplication'.

Being a miser (a proud one), I have never deployed this blog on any of the paid services. I've moved from essentially every Cloud services, using their free-tier while they lasted. After years of freeloading, I asked one of my good friends to deploy this app on his server. Since he could not give me remote access to his dedicated server and also envisaging the possibility of many more such shifts, I chose to leverage Docker.

Dockerfile specifies what will be included in your application container when it is executed. Using a Dockerfile allows us to define the container environment and avoid discrepancies with dependencies or runtime versions. Since my blog is developed using Express, dockerising it was pretty easy and adding the following content in the Dockerfile was virtually enough.

FROM node:boron-alpine

WORKDIR /usr/src/app

COPY package.json .

RUN npm install

COPY . .

EXPOSE 3004

CMD [ "npm", "start" ]

Before building the application image, let's add a .dockerignore file. It specifies which files and directories should not be copied over to your container.

node_modules
npm-debug.log
Dockerfile
.dockerignore

After successfully deploying to the server, the challenge that followed was publishing all the changes vis a vis modifying and updating the web application. For that, I leveraged the use of Github Webhooks. Using webhooks, every push made to the Github repository submits a post requests to a backdoor in the website. This then creates a child process to execute the following bash script.

#!/bin/sh

git pull --rebase

sudo docker image build -t ujjwalbhardwaj .

sudo docker stop $(sudo docker ps -a -q --filter ancestor=ujjwalbhardwaj --format="{{.ID}}")

sudo docker container run -it -p 443:3004 ujjwalbhardwaj

The backdoor requests are received and handled as follows:

router.post('/backdoor', function (req,res, next) {
  let hmac = crypto.createHmac('sha1', 'hello');
  const payload = req.body;

  hmac.update(JSON.stringify(payload));

  const calculatedSignature = 'sha1=' + hmac.digest('hex');

  if (req.headers['x-hub-signature'] === calculatedSignature) {
    const process = spawn("./redeploy.sh");

    process.on('exit', function (code) {
      console.log('child process exited with code ' + code);
    });
  } else {
    res.status(500);
  }

  res.end();
});