In a previous article, I provided a full step-by-step example of creating and running a Spring Boot web application that was packaged as a Docker image and run using the local Docker daemon.
In this article, I want to focus on the same Spring Boot REST web application, but without using Docker. Instead we will use buildah to create the OCI-compatible image, and then podman to run that image.
We will use a custom gradle task to invoke buildah to generate the image, and another task to run the container using podman.
Prerequisites
This article assumes you are on an Ubuntu development server. You will need the following packages installed.
OpenJDK 11+
# refresh package repos sudo apt update # show available openjdk versions sudo apt search openjdk-* | grep -P '^openjdk-1\d-jdk/' # pick latest (which is 17 as of this writing) sudo apt install openjdk-17-jdk curl git -y # validate version reported is the one just installed java --version
buildah and podman utilties
Use the instructions in my article on installing buildah and podman using a custom apt repository.
Code for article
Pull down the project from github.
git clone https://github.com/fabianlee/spring-boot-with-buildah.git cd spring-boot-with-buildah # compile and build Jar ./gradlew bootJar # build OCI image with buildah ./gradlew buildah # shows locally built images buildah images
We can see that the image has been built, but before we run it, let’s look deeper into the custom gradle tasks.
Modifications to build.gradle
‘buildah’ task
Here are the custom task definitions in build.gradle that allow us to invoke ‘gradle buildah’ and have an image generated.
task prepareDockerfileTemplate(type: Copy) { group "OCI" dependsOn "bootJar" from "src/main/resources/docker" include "Dockerfile" filter { it.replaceAll('<%=name%>', project.name) } filter { it.replaceAll('<%=version%>', project.version) } into "$buildDir" } task buildah(type: Exec) { group "OCI" dependsOn "prepareDockerfileTemplate" workingDir "${buildDir}" println "Executing 'buildah' task" commandLine "buildah", "bud", "-f", "Dockerfile", "-t", "springbootwithbuildah" }
The ‘prepareDockerfileTemplate’ is just a filter that uses the ‘src/main/resources/docker’ file as a template and places it into the ‘build’ directory with the correct name and version.
The ‘buildah’ task calls the prepareDockerfileTemplate as a prerequisite, then invokes the command below which will create the image.
buildah bud -f Dockerfile -t springbootwithbuildah
‘podman’ task
Here are the custom task definitions in build.gradle that allow us to invoke ‘gradle podman’ and run the image.
task podmanCleanup(type: Exec) { ignoreExitValue true commandLine "podman", "rm", "springbootwithbuildah" } task podman(type: Exec) { group "OCI" dependsOn podmanCleanup commandLine "podman", "run", "-p", "8080:8080", "-p", "8081:8081", "--name", "springbootwithbuildah", "springbootwithbuildah" }
The ‘podmanCleanup’ command makes sure any older containers using this name are removed.
The ‘podman’ task calls podmanCleanup as a prerequisite and then invokes the command below which runs the image as a container that is bound to the local ports 8080 and 8081.
podman run -p 8080:8080 -p 8081:8081 --name springbootwithbuildah springbootwithbuildah
Validate running container
This image exposes two ports: 8080 running the main REST api services, and another at 8081 which exposes actuator metrics.
Validate User Controller endpoint ‘:8080/api/user’ lists all users
The UserController.java exposes a REST compliant GET method at ‘/api/user’ that returns the list of currently known User objects in json format.
$ curl -s http://localhost:8080/api/user | jq [ { "name": "moe" }, { "name": "larry" }, { "name": "curly" } ]
Validate custom health check at ‘:8081/actuator/health’
The health check will return status=UP as long as the user count is greater than 0.
$ curl -s http://localhost:8081/actuator/health | jq { "status": "UP", "components": { "diskSpace": { "status": "UP", "details": { "total": 502467059712, "free": 385481076736, "threshold": 10485760, "exists": true } }, "ping": { "status": "UP" }, "user": { "status": "UP", "details": { "usercount": 3 } } } }
Cleanup
# this command OR Ctrl-C from console where it is running in foreground podman stop springbootwithbuildah # remove exited container podman rm springbootwithbuildah
REFERENCES
github project code, spring-boot-with-buildah
github jshift, buildah plugin for gradle
mavenlibs, jshift gradle plugin for buildah
NOTES
buildah to push local image to DockerHub
# owner/project:version OPV=fabianlee/springbootwithbuildah:1.0.0 buildah images $OPV # make sure login to DockerHub established buildah login --username <username> --password <password> docker.io # tag for remote Docker Hub, then push buildah tag localhost/$OPV docker.io/$OPV buildah push docker.io/$OPV