AWS CodeBuild Docker tutorial

AWS CodeBuild Docker tutorial

In this tutorial, we will build a CodeBuild project that builds a Docker image and pushes it to AWS ECR. CodeBuild is a fully managed build service by AWS. Compared to Jenkins which you have to be responsible for managing it, you don’t need to with CodeBuild.

CodeBuild is fast! Each build host can range from 3GB to 15GB ram.

CodeBuild environment specs:

Memory CPU Disk space
3 GB 2 64 GB
7 GB 4 128 GB
15 GB 8 128 GB

In this post, I will cover how to configure CodeBuild to build Docker images and push them to ECR.

Our repo is hosted in Github, and a build is triggered via an event hook. CodeBuild will start building the image and deploy it to ECR.

Create a Build Project

  1. Go to the CodeBuild console: https://console.aws.amazon.com/codesuite/codebuild/home
  2. Choose Create Project
  3. Project configuration: Enter the relevant details. It would be good to add some tags to make this project easily distinguishable.
  4. Source:this section will determine where the source code exists. Since we want the builds to be triggered by events we need to select “Repository in my GitHub account“.To make the deployment fast, set the “Git clone depth” to 1.

What is Git clone depth?

Git clone depth results in a fast git pull since we won’t clone the entire git history just 1 depth. This is important in a CI otherwise, if the project codebase is huge it will take a very long time to clone. Depth 1 is good since we only need to clone the latest revision for the build.

5.Configuring Github hooks for CodeBuild

In this section will configure how the builds should be triggered. We want it to be triggered on a push and when a Pull Request is submitted.

6. Build Environment

Every time we run a CodeBuild project, it launches a Docker container. Then it starts building the project. In this section, we will select on which Docker environment should our builds be run.

We are going to use the Ubuntu Docker with the PHP runtime.

You could also select a custom image. If you do select one, please ensure you have the required programs installed in the image to save time.

7. Buildspec

Similar to Jenkins which it has a JenkinFile. CodeBuild has Buildspec.yml.  It is a YAML file. This comes with a disadvantage as it is not flexible like JenkinFile.

CodeBuild looks for “buildspec.yml” in the root directory of the project.

8. Enabling Docker layer caching in CodeBuild

Since every build gets a new environment we would need to enable layer caching. With layer caching enabled our build will be significantly faster.

In the Artifacts section, select Local as the Cache type and check “Docker layer cache

Choose “Create build project”

Add ECR Policy

We would need to add “AmazonEC2ContainerRegistryPowerUser”?policy to our newly created role. This is because we would like to have our images pushed to ECR.

Creating the buildspec.yml

Inside the project create a file called. “buildspec.yml”. The buildspec has 5 main important phases (we would be using only 3 phases in our buildspec

 

  1. Install: In this phase, we could install the packages that the build stage. If you are noticing that your install phase is getting longer it would be good to install the packages in a custom image and use it as the running host in CodeBuild. We are not going to install Docker as it is already installed in the image so we skip this phase.
version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws --version
      - $(aws ecr get-login --region eu-west-1 --no-include-email)
      - REPOSITORY_URI=34643588447.dkr.ecr.eu-west-1.amazonaws.com/eagle
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_TAG=${COMMIT_HASH:=latest}
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build --tag $REPOSITORY_URI:latest  .
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker images...
      - docker push $REPOSITORY_URI:latest
      - echo Writing image definitions file...
      - printf '[{"name":"eagle","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
  files: imagedefinitions.json

2. pre_build: In this stage, we will authenticate with ECR so we could push the newly created image. We could also set variables in this stage to be used by the following stages. In our buildspec we will authenticate with ECR and create few variables:

REPOSITORY_URI: This the URI of the ECR repo which we will push to.

3. build: In this stage, we will write the build instructions. We will tag our build so we can, later on, use it to push it to ECR.

4. post_build: When the image build is successful we will push the image to ECR

When you pushed a commit or create a pull request the image will be built and pushed to ECR.