Creating a custom Java 8/Maven 3.6 Docker image and storing it at AWS ECR to use with AWS CodeBuild

Rodolfo Costa
4 min readSep 22, 2021

Depending on the tools used in an automated CI/CD pipeline, sometimes we may stumble upon some problems by only using the default tools provided by the services we make use of. That, unfortunately, happened to our team.

We utilize the highly efficient AWS CodeBuild to build and deploy apps in different languages. For that, we must specify the runtime version we want to run our pipeline. AWS has a list of available versions for multiple languages and we picked one of the Java compatible ones.

We kept using that specified runtime until one day we could not get to run the pipeline. The problem: the runtime comes, by default, with a Maven version incompatible for our applications, which is older than Maven 3.6. So we had to update Linux packages to update Maven to our required version before running our build commands, but, for some unknown reason, our AWS account could not connect to those repositories.

In order to workaround this, one solution was to create a custom Docker image containing all our required resources in their needed versions. This is where comes our custom Docker image with Java 8 and Maven 3.6.

The image

Thus, our custom image is created by using this simple Dockerfile:

We use as our base image “maven:3.6.3-openjdk-8” provided by Maven itself in their Docker Hub page (https://hub.docker.com/_/maven), which comes with OpenJDK 8 and Maven 3.6.3 pre-installed. Then, we install zip, unzip, curl and awscli so we can operate among AWS services we use to deploy our apps.

After built, this image will contain the following technologies:

  • Java 8 (with OpenJDK 8)
  • Apache Maven 3.6.3
  • AWS Command Line Interface (CLI) version 2

Nice! Now how do we store it in our AWS ECR?

Before building and pushing this customized Docker image, we must first create a repository in AWS ECR like shown bellow:

Setting the name of our image’s repository
Enabling scan on push (for security reasons)

For security reasons, we created a private repository named “codebuild/custom-maven-3–6–3-openjdk-8” since we only want AWS CodeBuild from our AWS account to have access to it. To enable this access, we must add the following permission to our repository’s permissions:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CodeBuildAccess",
"Effect": "Allow",
"Principal": {
"Service": "codebuild.amazonaws.com"
},
"Action": [
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer"
]
}
]
}

To add this permission, we must select our repository by clicking its name and, then, accessing the “Permissions” menu under “Repositories”.

Permissions menu

After adding the JSON policy, it will look like this:

Policy defined

Push! Push! Push!

Having Docker installed on your machine, after creating the repository, AWS gives the needed commands to have an image pushed under the “View push commands” button. Supposing our AWS account has the following

  • AWS account id: 123456
  • AWS ECR repository region: us-east-1
  • AWS ECR Repository name: codebuild/custom-maven-3–6–3-openjdk-8
  • Image tag: 1.0

and your configured default AWS user inside “~/.aws/credentials” file, the one awscli uses, has the “AmazonEC2ContainerRegistryFullAccess” policy, the commands will be:

  1. Authenticate your Docker client with the registry
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456.dkr.ecr.us-east-1.amazonaws.com

2. Build our customized Docker image

docker build -t my-custom-image:maven-3-6-3-openjdk-8 .

3. Tag our image

docker tag my-custom-image:maven-3-6-3-openjdk-8 123456.dkr.ecr.us-east-1.amazonaws.com/codebuild/custom-maven-3-6-3-openjdk-8:1.0

4. Push to the registry

docker push 123456.dkr.ecr.us-east-1.amazonaws.com/codebuild/custom-maven-3-6-3-openjdk-8:1.0

After running them, the image should be in our repository.

Stored image

With this setup, we can finally update our CodeBuild project environment settings to utilize this custom image under “Edit” > “Environment”.

CodeBuild environment image settings

Awesome!! However, before running your next build, you have to update your buildspec file and remove the snippet related to specifying the old runtime and voilà! You have your CodeBuild project using a custom runtime image.

Conclusion

Even knowing that it is always easier to use default tools provided by the services we depend on, sometimes we may need customized solutions to increase reliability and stability in our processes.

The case shown here can be applied to any project with any language by only changing the base image, which, indirectly, helps standardizing the CI/CD process among team’s projects.

References

--

--