|

Build Spring Boot multi arch docker images with GitHub actions.

In this blog post, I will show you how to build multi arch docker images of Spring Boot applications with GitHub actions. This is useful for building images that can be run on system with different architectures.

In one of my previous blog post, I have shown you how to build spring boot application multi arch docker image in local development system and push them to docker hub.

In this post, we will use GitHub actions CI/CD pipeline to automate the building of docker images and publish them to docker hub.

Why we need Multi-Arch images?

Earlier application used to run on x86/x86-64 architecture (i.e Intel/AMD processors) based processors. With introduction of Apple M1/M2 based processors which are based on ARM64 architecture , now developers need to support multiple architectures so that their application runs on machines that support ARM architecture.

Cloud provides like amazon and oracle are providing ARM64 based compute instances at lesser price compared to the x86 based instances.

As developers seek to create applications compatible with various hardware architectures, the need to build and deploy these applications efficiently and uniformly is crucial.

GitHub Actions provide a versatile and user-friendly platform for managing CI/CD workflows

GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate the build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.

Creating Dockerfile

Let’s use following docker file create spring boot application docker image.

FROM eclipse-temurin:17.0.6_10-jdk-jammy
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
RUN addgroup --system springboot && adduser --system sbuser && adduser sbuser springboot
USER sbuser
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]Code language: Java (java)

Generating Docker Token

Using GitHub action we going to generate the docker image and push it to docker hub. To push docker image into docker registry we need to login from GitHub action. To login into docker registry, we need to generate the docker token which acts as password.

Log into hub.docker.com

Open your account settings by clicking on <user-name>/Account settings.

Click on “Security” link on the left side menu.

Generate new token by clicking on the “New Access Token” button

Note down the access token.

Creating GitHub Secrets

GitHub actions file is publicly accessible, so we can not store sensitive information in the actions file. Secrets are encrypted variables that we create in repository, or repository environment.

  1. On GitHub.com, navigate to the main page of the repository.
  2. Under repository name, click  Settings.

3.In the “Security” section of the sidebar, select  Secrets and variables, then click Actions.

4.Click the Secrets tab.

5.Click New repository secret.

6.Type a name for your secret in the Name input box.

7.Enter the value for your secret

8.Click Add secret

We have to store all the sensitive information in secrets. We are going to create following secrets.

  • DOCKER_USERNAME
  • DOCKER_TOKEN

Creating GitHub Action Files

Next we create action file which contains the work flow steps.

Create .github/workflows directory in root of your projects.

inside workflows folder create “deployment.yml” file and place following code.

name: Docker Multi-Arch

env:
  IMAGE_NAME: sureshgkhyd/sb-crud-image
  DOCKER_REGISTRY: docker.io

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  publish-app:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: |
          echo "IMAGE_NAME_WITH_REGISTRY=$DOCKER_REGISTRY/$IMAGE_NAME" >> $GITHUB_ENV
          export IMAGE_NAME_WITH_REGISTRY=$DOCKER_REGISTRY/$IMAGE_NAME
          echo "FULL_IMAGE_NAME=$IMAGE_NAME_WITH_REGISTRY:latest" >> $GITHUB_ENV
      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'
          cache: maven
      - name: Build with Maven
        run: mvn --batch-mode --update-snapshots package
      - name: Login to Docker Hub
        uses:  docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_TOKEN }}
      - name: Setup Docker buildx
        uses: docker/setup-buildx-action@v2
      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags:
              ${{ env.FULL_IMAGE_NAME }}
              ${{ env.IMAGE_NAME_WITH_REGISTRY }}:${{ github.sha }}Code language: Java (java)

When ever we push the code to github, action will trigger and push the docker image to dockerhub.

You can download the source code of project from GitHub

Using Multistage Docker file

In above scenario we were using simple docker file, Let’s use the below multi stage docker file.

FROM maven:3.9.0-eclipse-temurin-17 as build
COPY pom.xml pom.xml
COPY src src
RUN mvn --batch-mode clean package

FROM eclipse-temurin:17.0.6_10-jdk-jammy
COPY --from=build "./target/*.jar" /app.jar
RUN addgroup --system springboot && adduser --system sbuser && adduser sbuser springboot
USER sbuser
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]Code language: Java (java)

If you observe above docker file, it already contains maven and JDK are already setup inside image.

So when we write action file to automate the docker image creation then there is no need to setup JDK and Maven. We just need to setup docker and build the image.

GitHub Action File

Below action file can be used to build and push docker images

name: Docker Multi-Arch

env:
  IMAGE_NAME: sureshgkhyd/sb-crud-image
  DOCKER_REGISTRY: docker.io

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  publish-app:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: |
          echo "IMAGE_NAME_WITH_REGISTRY=$DOCKER_REGISTRY/$IMAGE_NAME" >> $GITHUB_ENV
          export IMAGE_NAME_WITH_REGISTRY=$DOCKER_REGISTRY/$IMAGE_NAME
          echo "FULL_IMAGE_NAME=$IMAGE_NAME_WITH_REGISTRY:latest" >> $GITHUB_ENV
      - name: Login to Docker Hub
        uses:  docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_TOKEN }}
      - name: Setup Docker buildx
        uses: docker/setup-buildx-action@v2
      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
              ${{ env.FULL_IMAGE_NAME }}
              ${{ env.IMAGE_NAME_WITH_REGISTRY }}:${{ github.sha }}Code language: Java (java)

You can download the source code of project from GitHub

Similar Posts