Sunday, November 21, 2021

Docker DevOps to deploy an ExpressJS app to Azure using DockerHub

 This docker architecture will create a continuous integration and deployment pipeline using GitHub for code repository, DockerHub for Docker image repository and Azure for deploying the app through Docker containers.

After the whole setup, you will be able to make code changes. Once you push the changes to GitHub to the branches you have created, it will automatically be deployed to Azure.

Backstory

If you are asking why Azure instead of AWS or GCloud, I feel you. As many developers working on their personal projects, we rely on free subscriptions and free credits. For me, I had more credits with Azure. It was working fine for some time. Then, it started acting up. By that, I mean really acting up. I got all sorts of errors while deploying the application (PS: I did not get any issues with AWS). It was all library issues. It was giving all sorts of npm package not found/module not found errors. Before these errors, it was working fine for about 2 months. That’s what I get for depending on the Azure machines blindly. So, one morning, I just decided to dockerize the whole app and deploy it to Azure.

Solving through Dockers

I decided to use Docker Containers to get rid of Azure’s soap opera drama. Let me give you a brief overview of what Docker is and how it solves all the deployment issues.

If you are already familiar with Docker, you can skip to Step 1.

What’s Docker?

It is basically a tool that allows us to create, deploy and run our applications using a container. Docker containers allow us to package our entire application (libraries and all dependencies) and ships it as one package. This way you don’t care where you are deploying your application or what libraries the hosting machine has. You will have everything you need inside a container you create. You are in charge here.

A traditional flow is:

You have an application > Create a docker image with all dependencies you need > Run a container.

I cannot explain the whole docker in a paragraph but Docker solves many issues. Especially, if you are a Data Scientist and running multiple Machine Learning models, deploying them to multiple machines gives all sorts of library version mismatch problems. I have personally had them in past projects. With Docker, you don’t have to hire an extra person for solving deployment issues because chances are you won’t have any.

More on Docker: follow this and this.

Prerequisites

You at least need these accounts to get started with. Follow the links if you don’t have one.

  1. GitHub repo
  2. DockerHub account setup
  3. MS Azure account

Assumption

I am assuming that you already have some knowledge of Git and you already have a project in GitHub. If you are looking at this article, you probably have a project and want to deploy it to the cloud.

Step 1: Create a Dockerfile in the root of your Express project

If you don’t have a project setup, please follow instructions on express-generator or boilerplate here with nodemon and babel already setup. Then, set it up with GitHub.

Create a Dockerfile in the root of your project. Dockerfile is a document with all the commands that docker build builds the image from.

FROM mhart/alpine-node:8WORKDIR /appRUN npm installRUN npm run buildCOPY . /app/EXPOSE 3000CMD [ “npm”, “start” ]

The above code creates an image from alpine-node as a base image. I am using alpine-node because it is very light compared to the official node image.

alpine-node image size: ~65 MB
Official Node Image: ~900 MB

Create .dockerignore file

Once you are done with Dockerfile, create a .dockerignore file. Similar to .gitignore, this file ignores the files/directories mentioned inside the file. Typically, a starter Express projects can have these files:

node_modules
npm-debug.log

We want to exclude node_modules because when building the image, we are doing npm install in the Dockerfile.

Since we will be building Docker images through GitHub, you don’t need to include node_modules but it helps if you are trying to build locally.

You can test this locally by creating an image in docker locally. You need a docker app for your windows/Mac. However, for preventing this article from being too long, I won’t go into local builds.

Step 2: Create a Docker Repository and connect it to GitHub

You need to create a docker repository first. You can create one docker repository for each GitHub project. You can have multiple images for different branches. So, if you plan on having different stages of your application like DEV, TEST, and PROD, you can do so by creating multiple docker images with tags like dev, prod, test. You need to have your images in your remote repository so that Azure can continuously deploy from your app’s image. We will use the DockerHub. Once you login into DockerHub, create a repository

  1. Select your GitHub user name and the repository you want to create docker image for.
  2. Customize the build settings to create different images for different branches. For this scenario, we will do 2 images: one for production and one for development.
  3. Docker Tags are important as they differentiate your images.
  4. Enter the Dockerfile location from the root of your project. Usually, Dockerfiles are kept in the root of the project.
  5. Also, select Autobuild so that when you push code changes to GitHub, docker image automatically rebuilds.
  6. When you have everything filled out, create and build.

If you do not see Autobuild option, go to your repository > builds > Configure Automated Build

You can check the build process through the Build tab. You cannot miss it.

Step 3: Running the docker image in Azure’s container

After your image build has passed, head over to Azure Portal to create a project. We’ll create a continuous deployment in Azure Web App by pointing it to DockerHub.

For the purpose of this tutorial, we will stick with Single Container deployment because both Docker Compose and Kubernetes in Azure are in the “Preview” currently. If you want to deploy multiple containers in a single environment, go with other options. However, if you are done with the basics and are interested in doing more, you should checkout Kubernetes. It’s very cool.

Follow the instructions below

  1. After logging in to Azure Portal, create a resource and search for Web App. Create a web app
  2. Enter the name for the web app, subscriptions, resource group, and all the required fields on the left-hand side.
  3. In Publish, choose docker. Then, you will see a new option Configure Container.
  4. Go to configure container and choose Single Container -> Docker. Depending on the public/private DockerHub image, you will be asked to enter credentials. Enter DockerHub credentials for private repo.
  5. In the image option: enter the name in the specified format: {userAccount}/{repo name}:{tag name}
  6. Tag names are dev and prod we created earlier.
  7. You can leave the Startup File empty.
  8. Apply the changes and create.
  9. After the resource is created, open it and go to Container Settings to turn on the Continuous Deployment. This is where the magic happens (not really magic)

Step 4: Adding environment variables

This is an optional step if you have the environment variables you haven’t included with the project.

This step is necessary when you have different environments like DEV and PROD and you don’t want to keep sensitive information in your GitHub because you don’t want all developers knowing your credentials to various APIs, secret keys and other tool credentials.

You can enter the environment variables used by your Express app directly into Application Settings in Azure. It will be accessible to your Node application. For example, if you want to run the app differently according to NODE_ENV variable like:

if (process.env.NODE_ENV == ‘production’) {// Do something when NODE_ENV is for productionelse {// Do something if it is not.// If you provided other environment keys through Azure, you can      access it in Express code like process.env.DATABASE_PASSWORD// It is if you provided DATABASE_PASSWORD in Azure’s Application Settings the same way as NODE_ENV}

For adding the environment variables in Azure, go to Application Settings and add the variables there like below:

No comments:

Post a Comment