The Future is Here: Docker Image Building with Monorepo Architecture and CircleCI

The Future is Here: Docker Image Building with Monorepo Architecture and CircleCI

Overview :-

In the rapidly evolving world of software development, efficiency and scalability are paramount. The integration of Docker with Monorepo architecture, especially when automated through CircleCI, represents a significant leap forward. This approach not only simplifies the development process but also enhances the overall workflow. Let’s delve into how these technologies converge to streamline project management and deployment.

Pre-requisites :-

Before diving into the procedure, it’s essential to understand the foundational tools and concepts involved:

  • Docker: A platform that uses OS-level virtualization to deliver software in packages called containers.

  • Monorepo: A version control strategy where code for many projects is stored in the same repository.

  • CircleCI: A Continuous Integration/Continuous Deployment (CI/CD) platform that automates the development process.

Familiarity with basic command-line operations and version control with Git is also beneficial.

Procedure :-

Setting Up Your Environmen

1. Prepare Your Monorepo: Organize your projects within a single repository. Tools like Lerna or Yarn Workspaces can help manage dependencies and scripts across multiple packages.

Integrating CircleCI

1. CircleCI Configuration:- Create a .circleci directory in your monorepo root and add a config.yml file. This file will define your build, test, and deployment pipelines.
2. Optimizing for Monorepo:- Utilize CircleCI’s powerful caching mechanisms to avoid rebuilding unchanged parts of the repository. This can significantly reduce build times.

Building Docker Images

  • Dockerfile Creation: create one Dockerfile for all the projects in your monorepo. This file contains the instructions for building the Docker image.

  • CircleCI Automation: Modify the config.yml to automate Docker image building. Use CircleCI’s docker commands to build and push images to a Docker registry. Below is the example config.

version: 2.1

jobs:
  detect_changes:
    docker:
      - image: cimg/python:3.8
    steps:
      - checkout
      - run:
          name: Detect changes
          command: |
            mkdir -p /tmp/workspace

            if [ ! -f /tmp/workspace/changed_projects.txt ]; then
              touch /tmp/workspace/changed_projects.txt
            fi

            IGNORED_FOLDERS=("project_4")

            CHANGED_FILES=$(git diff --name-only $CIRCLE_SHA1 $CIRCLE_SHA1~1)
            echo "Changed files: ${CHANGED_FILES}"

            COMMON_CHANGED=false

            if echo "${CHANGED_FILES}" | grep "^projects/project_1/"; then
              COMMON_CHANGED=true
              echo "projects/project_1 directory has changed"
            fi

            for DIR in projects/project_*; do
              if [ -d "${DIR}" ]; then
                PROJECT_NAME=$(basename ${DIR})
                if echo "${CHANGED_FILES}" | grep "^${DIR}/"; then
                  echo "${PROJECT_NAME}" >> /tmp/workspace/changed_projects.txt
                  echo "${PROJECT_NAME} directory has changed"
                fi
                if [ "$COMMON_CHANGED" = true ]; then
                  echo "${PROJECT_NAME}" >> /tmp/workspace/changed_projects.txt
                fi
              fi
            done

            sort /tmp/workspace/changed_projects.txt | uniq > /tmp/workspace/changed_projects_sorted.txt
            mv /tmp/workspace/changed_projects_sorted.txt /tmp/workspace/changed_projects.txt
            cat /tmp/workspace/changed_projects.txt

      - persist_to_workspace:
          root: /tmp/workspace
          paths:
            - changed_projects.txt

  build_and_push:
    docker:
      - image: circleci/python:3.8
    environment:
      ENV_FILE: /tmp/workspace/.circleenv
      DOCKER_BUILDKIT: "1"
      BUILDKIT_PROGRESS: plain    
    steps:
      - checkout
      - attach_workspace:
          at: /tmp/workspace
      - setup_remote_docker:
          version: 20.10.7
      - run:
          name: Login to ECR
          command: |
            aws --profile infra ecr get-login-password | \
              docker login -u AWS --password-stdin https://${AWS_ECR_REGISTRY_URL}     
      - run:
          name: Build and Push Docker Images
          command: |
            build_and_push() {
              PROJECT_NAME=$1
              echo "Building ${PROJECT_NAME} Docker image"
              docker build -t ${PROJECT_NAME}:latest -f ./projects/Dockerfile .

              echo "Tagging Docker Image"
              docker tag ${PROJECT_NAME}:latest ${AWS_ECR_REGISTRY_URL}/${PROJECT_NAME}:$CIRCLE_BRANCH

              echo "Push Docker Image"
              docker push ${AWS_ECR_REGISTRY_URL}/${PROJECT_NAME}:$CIRCLE_BRANCH
            }

            if [ -f /tmp/workspace/changed_projects.txt ]; then
              while IFS= read -r PROJECT_NAME; do
                build_and_push ${PROJECT_NAME}
              done < /tmp/workspace/changed_projects.txt
            else
              echo "No changes detected in any projects."
            fi

workflows:
  version: 2
  build-and-deploy:
    jobs:
      - detect_changes
      - build_and_push:
          requires:
            - detect_changes

Continuous Integration and Deployment

1. Automate Testing: Configure CircleCI to run tests for each commit. This ensures that only passing builds are deployed.
2. Deployment: Set up automatic deployment to your chosen service (e.g., AWS, Google Cloud) upon successful builds and tests.

3. Make sure you should pass the AWS_ECR_REGISTRY_URL as an environment variable in circleci.

Conclusion :-

Adopting Docker with Monorepo architecture streamlined by CircleCI can transform the complexity of managing multiple projects into a more manageable and efficient process. This setup not only speeds up the development cycle but also ensures consistency across different environments. As we embrace these advanced tools, the future of software development not only looks bright but also more interconnected. Embrace this integration to keep your projects cutting-edge and market-ready.