Continuous Integration and Continuous Delivery (CI/CD): GitHub Actions is a platform that lets you automate your build, test, and deployment pipeline. You can set up workflows that build and test every pull request to your repository, or you can deploy merged pull requests to production.
Requirements
- A gradle Spring Boot project to be dockerized
- GitHub repository
- Docker Hub account
What are we going to build?
We will set up a GitHub workflow to build Docker images that will run automatically whenever commits are pushed to the repository.
Getting started
For this job, there are many tips and tricks that can be used. This method is a very easy and straightforward way to get there.
The Docker Hub
We need to make a repository on Docker Hub. That’s where the container images we create will be pushed.
Dockerfile
Let’s get started by creating a Dockerfile.
Because this is a Spring Boot project, we’ll use the openjdk Docker image and a jar file compiled from the Gradle.
Dockerfile
FROM openjdk:8-jdk
RUN mkdir /app
COPY app.jar /app/app.jar
WORKDIR /app
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Github Actions
Fun part. The most exciting part is to see what Github Actions can do to help us automatically build Gradle and Docker images without human intervention.
Let’s create a main.yml
file in .github/workflows
folder.
The workflows would consist of two separate jobs
- build: to build jar file
- build-image: to build Docker image and push to it Docker hub
Build Jar file
The very first job of the pipeline is to build a jar file for the Spring Boot application. The simplest way to get started is to look for a sample Github workflow on Github.
- Go to Github Repo
- Actions
You will see workflows that could be used with your repository. In this case, it seems like the best way to build Spring Boot’s jar file is to use Java with Gradle workflow.
- Click on
Configure
button
main.yml
Let’s use the above sample workflows to make main.yml
file.
The should look like
This is how main.yml
should look:
name: Docker CI with Gradle
on:
push:
branches: [ "main" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Execute Gradle build
run: |
chmod +x ./gradlew
./gradlew bootJar
- name: Execute Gradle build
run: |
chmod +x ./gradlew
./gradlew bootJar
- name: Copy Jar file
run: mv build/libs/$(ls build/libs) app.jar
- uses: actions/upload-artifact@master
with:
name: jar-file
path: app.jar
- I’ve replaced the
gradle build
with./gradlew bootJar
as this Spring Boot App comes with its own gradle wrapper. - I also moved the compiled
app.jar
from the build directory to the current directory because the Dockerfile expects it to be in that location. - To be able to share the jar file with the next job (build-image that we’re going to do later) by using upload-artifact actions.
Let’s add the main.yml
file and push it to Github repo.
If everything was set up right, the workflow would be running on the Github actions page.
Build Docker Image
Just like we did for the last job, we can find a lot of public examples of workflows.
build-image:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@master
with:
name: jar-file
path: app.jar
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set env
run: echo "DATE=$(date +%s)" >> $GITHUB_ENV
- name: Build and push
uses: docker/build-push-action@v3
with:
context: .
push: true
tags: thearaseng/dockerized-spring-boot-app:${{ env.DATE }}
noted that we need to create two important variables: DOCKERHUB_USERNAME
and DOCKERHUB_TOKEN
Generate Docker Hub Access Token
Because we’re going to push the images to Docker Hub, we need an access token with read and write permission.
To generate this access token.
- Go to Docker Hub setting page: https://hub.docker.com/settings/security
- Click on
New Access Token
button
- Fill out the Access Token Description field
- In Access permission dropdown, choose
Read & Write
- Click on
Generate
button
- Make a copy of the access token and don’t give it to anyone else.
Github Actions secrets
Since they are very sensitive variables, we are going to store them in Github Actions secrets.
- Go to Settings > Secrets > Actions
- Click on
New repository secret
button
- Fill out the Docker Hub account name
- Fill out the Docker Hub access token
Final Result
Let’s commit the final main.yml
file and go to the Github Actions page
Github Actions
Docker Repo
We can see Docker tags that have been pushed from Github Actions.
Congratulations. You made it. :)
You can find the complete source code on the public Gitlab Repo.
https://github.com/thearaseng/dockerized-spring-boot-app/tree/main
Peace!