CodePipeline for a Micronaut application Docker image

By Sergio del Amo - Tue, 25 May 2021 12:57:27 GMT

Tags: #micronaut #aws #ecr #codebuild #elasticbeanstalk #codebuild #codepipeline #docker

Continuous deployment - CodePipeline: Github → CodeBuild → ECR → Elastic Beanstalk

Micronaut is build agnostic, you can use either Gradle or Maven. However, Gradle is my build tool of choice.

Changes to Gradle Build

Generate Dockerrun.aws.json

Create a template for Dockerrun.aws.json

A Dockerrun.aws.json file describes how to deploy a remote Docker image as an Elastic Beanstalk application. This JSON file is specific to Elastic Beanstalk. If your application runs on an image that is available in a hosted repository, you can specify the image in a Dockerrun.

Dockerrun.aws.json

{
    "AWSEBDockerrunVersion": "1",
    "Image": {
        "Name": "@awsAccountId@.dkr.ecr.@awsRegion@.amazonaws.com/@awsEcrRepositoryName@:@imageTag@",
        "Update": "true"
    },
    "Ports": [
        {
            "ContainerPort": "5000"
        }
    ]
}    

I define the properties in gradle.properties

projectVersion=0.0.5
...
awsAccountId=XXXXXXX
awsRegion=us-east-1
awsEcrRepositoryName=YYYYY

Create a Gradle tasks to populate the JSON template:

build.gradle

import org.apache.tools.ant.filters.ReplaceTokens
task copyAndReplaceTokensFromDockerrun(type: Copy) {
    from('Dockerrun.aws.json') {
        include 'Dockerrun.aws.json'
        filter(ReplaceTokens, tokens: [imageTag: projectVersion,
                                       awsAccountId: awsAccountId,
                                       awsRegion: awsRegion,
                                       awsEcrRepositoryName: awsEcrRepositoryName])
    }
    into 'build/docker'
}

Configure Container registry

Configure the Amazon ECR repository as the container registry:

build.gradle

version = projectVersion

...
..
.

dockerBuild {
  images = ["${awsAccountId}.dkr.ecr.${awsRegion}.amazonaws.com/${awsEcrRepositoryName}:$project.version"]
}

AWS CodeBuild

When you create your CodeBuild project, in the environment section, check:

[x] Enable this flag if you want to build Docker images or want your builds to get elevated privileges`

BuildSpec

Create buildspec.yml file:

A buildspec is a collection of build commands and related settings, in YAML format, that CodeBuild uses to run a build.

version: 0.2

phases:
  install:
    runtime-versions:
      java: corretto11 
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)
  build:
    commands:
      - ./gradlew dockerPush
      - ./gradlew copyAndReplaceTokensFromDockerrun
  post_build:
    finally:
      - rm -f  /root/.gradle/caches/modules-2/modules-2.lock
      - rm -fr /root/.gradle/caches/*/plugin-resolution/
artifacts:
  files:
    - 'Dockerrun.aws.json'
  base-directory: 'build/docker'
cache:
  paths:
    - '/root/.gradle/caches/**/*' 
    - '/root/.gradle/wrapper/**/*'

The build's artifact is the output of the Gradle copyAndReplaceTokensFromDockerrun task.

AWS Code Build IAM Role

Attach a policy to the IAM role used by AWS CodeBuild to allow the build to publishing a new image to a Amazon ECR repository. For example, the AWS Managed policy AmazonEC2ContainerRegistryPowerUser.

Elastic Beanstalk

Create a Web server environment. As platform select Docker running on a 64bit Amazon Linux 2.

AWS Elastic Beanstalk IAM Role

Attach a policy to the EC2 IAM role used by AWS Elastic Beanstalk to allow the environment to retrieve the image from Amazon ECR repository. For example, the AWS Managed policy AmazonEC2ContainerRegistryReadOnly.

Start Micronaut Application in port 5000

Set environment variable MICRONAUT_SERVER_PORT with value 5000 in AWS Elastic Beanstalk Configuration → Software.

AWS CodePipeline

AWS CodePipeline:

  • Source: Github (Version 2)
  • Build Provider: AWS CodeBuild
  • Deploy Provider: AWS Elastic Beanstalk