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’sdocker
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.