Putting Everything Together (Introducing mujik)

  • by

Hi there! It’s definitely been a while! For the past couple of weeks I’ve largely been occupied with finishing up my degree. And as Steve Kerr says, “the closeout game is always the hardest game in every series”. That couldn’t be more true as senioritis has kicked in and things don’t get easier when your college experience is now limited to a series of Zoom calls throughout the week. Nonetheless, as I have been pining away at my assignments something wonderful has been brewing behind the scenes. What’s great is that one of my classes is an ideal, “two birds with one stone” situation.

In case you’re not aware, this past summer me and a couple of my close friends all got together to complete a fullstack web developer course to add new skills to our toolkit before hiring season begins and also just for fun! The whole exercise was a massive success but we weren’t able to stick the landing. Our hope was to have a capstone project to finish things off but due to a multitude of ahem* “issues” we all weren’t able to dedicate enough time to actually put the icing on the proverbial cake. But thankfully, Gaurav, Atharva and I were all enrolled in a class where the objective was ultimately, to create a full stack web application! Well now we had to bring everything we learned over the summer to the table, not just for fun, but because our graduation from Stony Brook depended on it! Fun!

The Objective

For this class we are required to create a web app using the MERN stack. If you are somehow not aware, the MERN stack stands for and application created with MongoDB, Express, React, and Node. These days, it is almost considered a rite-of-passage for any recent college grad. to have created a couple of web apps with the MERN stack or some close variation of it. Just a few years ago, this same class used to be about create a large scale project using JavaEE and Swing. Those days are now behind us… *shudders*.

Using the MERN stack we are tasked with creating a music streaming service akin to Spotify or YouTube Music. We were also expected to add some sort of “spin” on top of it to differentiate it from other services. As far as retrieving the music and playing it, we were expected to use the APIs of the services mentioned before.

As much as I would like to go in detail about what our project is… you must understand that at the time of writing the class is still ongoing and revealing our project might expose our secret sauce to other groups in the class as well. The class itself is not a competition but… it kind of is. At least we are treating it as such since we personally know a lot of the people in the class. All we can tell you is, the name of our service is mujik and it’s gonna be pretty f***ing great. I promise you.

The DevOps side of things

Since we all already had a great deal of experience over the summer with web apps, I personally wanted to add a little spice to make it an even better learning exercise. Because of this, our group decided to create an end-to-end full CI/CD pipeline for the project. While there are some great ways to easily deploy a simple webapp (Vercel and Netlify come to mind), the trickier part would be the backend. The dependencies for just the front end are the static files and simple web server (nginx is what we’ll be using). For the back end it’s the API, the database, any caching services and anything else you might need.

I also personally wanted to put into practice what I learned about Kubernetes and Amazon ECS. Because of this, I dockerized mujik. And also utilized GitHub Actions to publish our images to the DockerHub on each push/merge on our master branch. If you’d like to dockerize your React app, I would highly recommend following this excellent guide written by Michael Herman. For fun, I wanted to create a workflow which would run some tests, build the docker image, push it to Amazon ECR then deploy the image to Amazon ECS. You can see the workflow below…

# .github/workflows/main.yml
# GitHub workflow for testing and deploying mujik-web to AWS ECS.

name: CI

on:
  push:
    branches: [ master ]

jobs:
  # Run basic tests.
  test_and_deploy:
    runs-on: ubuntu-latest
    steps:

      # Checkout code and run tests.
      - uses: actions/checkout@v2
      - name: Setup Node.js environment
        uses: actions/setup-node@v1.4.3
        with:
          node-version: 12.18.3
      - name: Install Packages
        run: yarn install
      - name: Run Tests
        run: yarn test

      # Start deploying.
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

      - name: Build, tag and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: mujik-web
          IMAGE_TAG: prod
        run: |
          # Build a docker container
          # and push it to ECR so that it can be deployed to ECS.
          docker build -f Dockerfile.prod -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"

      - name: Fill in the new image ID in the Amazon ECS task definition
        id: task-def
        uses: aws-actions/amazon-ecs-render-task-definition@v1
        with:
          task-definition: task-definition.json
          container-name: mujik-web
          image: ${{ steps.build-image.outputs.image }}

      - name: Deploy Amazon ECS task definition
        uses: aws-actions/amazon-ecs-deploy-task-definition@v1
        with:
          task-definition: ${{ steps.task-def.outputs.task-definition }}
          service: mujik-web-service
          cluster: mujik-web
          wait-for-service-stability: true

There are many many excellent guides on how to get started with GitHub Actions and I would highly recommend that you try and research it on your own. The official GitHub Actions wiki is a great start. We don’t need to deploy to ECS and the sad part is, on each deploy the IP address changes for our service, unless we are willing to fork out $18/month for an ALB (Application Load Balancer). Because of this, we are sticking to Vercel and when the need arises I will have to come up with a creative solution to create a reverse proxy which will point to the IP of our latest container through some magic with our GitHub Actions. Again, fun!

More Updates?

I hope this blog post is the start of a more consistent schedule for blog posts. I can’t make any promises but I’ve definitely got the bug again to post. I hope my journey on becoming a better developer can maybe help some other people as well. The content I learned over the summer was very generalized and bit out of place. For the foreseeable future, I will be focusing this blog on distributed systems, databases, Linux, and creating data pipelines. Of course if I see something cool I will be sure to share it on here as well!