Spring Boot + Docker for Kubernetes | Building container Images

TheCodeAlchemist · Intermediate ·☁️ DevOps & Cloud ·2mo ago

Key Takeaways

Builds container images for Spring Boot applications using Docker and Kubernetes

Full Transcript

Hey everyone, welcome back. Starting today, we are kicking off a new series on Spring Boot and Kubernetes. So, this series will be about understanding how real Spring Boot applications, Java applications, are deployed onto the Kubernetes. In this series, we will build a system step-by-step, and it will include multiple services, and these multiple services talking to each other backed by the databases. We will also learn the caching, messaging, scaling, and everything throughout the series. Now, before we start anything, we need to understand one important thing what this series is not about. So, this is not a Kubernetes course. Of course, it's going to be a hands-on guide on how to deploy Spring Boot applications, how they actually run on Kubernetes, but this course is not about Kubernetes. So, we are not going to learn all the Kubernetes commands. We are not going to dive deep into Kubernetes. This course does not guarantee you the Kubernetes admin or the developer path. All right? So, we will touch all the important concepts of Kubernetes as they belong in the journey of deploying the Spring Boot application onto Kubernetes. This series is a developer-focused, hands-on series, and everything that we will cover, everything that we will explain, it will be from the Spring Boot point of view. So, having set this stage, let's get started. So, at a very high level, Kubernetes is just a system that manages containers for you. It doesn't care about your code or your framework. It only understands the containers. So, Kubernetes takes your container, it runs your container across different machines, different nodes. It monitors them, it keeps them alive, and it also is scales the containers depending on the configuration. And then, it takes care of routing the traffic to your containers, to your application. Okay? So, that is why we will start this journey with the container images, because ultimately, Kubernetes understands the container. So, you can see on the right-hand side that Kubernetes is actually running the pod, and the pod needs the image. So, that is where we will start. We will have the application, we will write the application, then we will create the container image so that we can run the application in Kubernetes using pod. Okay? So, in the first video, we will learn how to build the container images for the applications. And in this video, we will cover four things, four different ways to create the container images. The first one would be the Spring Boot image plugin, then we will learn how to create images using Google Jib plugin, and the last two are related, that is where you write the Dockerfile yourself, hence the DIY Dockerfile, and then multi-stage Dockerfile. So, we will see these four ways to create the application container images. So, for the demo, we need a demo application so that we can test the deployment on Kubernetes. And here, we have a very simple Spring Boot application that I created using Spring Initializr. It has a single class, and it has a single controller that is only returning the status of the API demo endpoint. All right? It has no other functionality, because the purpose here is to learn how to create the container images for a Spring Boot application, and the same strategy we can apply to any Spring Boot application. So, that is why this application is kept simple. So, if we check out the pom.xml and dependencies, you can see it has only Spring Boot web dependency, because this has to support the controller, and that's it. So, what else do we need to create the container image? Since we are going to cover Spring Boot image plugin first, we need the application that we already have, and second, we need to have the Docker running. On my Mac, I have the Docker Desktop, which is running, so I have the Docker daemon. All right? So, in case you don't have the Docker Desktop, you can install it, and you need to have it running so that you have a Docker daemon running on your system. Now, in order to use Spring Boot image plugin, we don't have to do anything special, because it comes out of the box when you create the Spring Boot application. To understand how the plugin works, what it needs, we can check out the official documentation that you will see here. I will share the link with the video description, but all the details related to the plugin, we will find on this page. As we can see, to use the plugin, this is dependent on the Spring Boot Maven plugin, and that's all we need. And we know that when we create the Spring Boot application, we already get this plugin in the pom.xml. Down below on the documentation page, we can see some examples on how to configure certain things when it comes to the image. So, you can see we are still using the same plugin, but there is this configuration tag, and in this configuration tag, we can configure some aspects of the images. Like in this example, this is basically showing how to configure builder and run image under the image tag. And in the same way, we can do other things as well, like creating the environment variables that you can use in the image, or something like this. So, here we are setting HTTP proxy and HTTPS proxy environment variables to XYZ values. So, the idea is you can use configuration tag to configure some things about the image creation process. So, for the demo, in this example, we will configure the name of the image. That means anytime when you run the plugin, it will create the image with a certain name. All right? This is basically to set the standard for the image name, so that you always have the consistent naming. So, let's go back to the IntelliJ and configure this plugin. So, the good thing is any Spring Boot project that we create using a Spring Initializr, it already has the Spring Boot Maven plugin. So, that means we don't have to do anything extra. We can verify here as well. In the Maven widget, if you notice, we can see all the plugins, and there is the Spring Boot, and under the Spring Boot, we can see there are plugins like build image, which is the same plugin that we are going to use. Again, it just shows you that just by creating the Spring Boot project, you already have access to this plugin. The additional thing that we will do, we will configure the name of the image, and we already know from the documentation that we need to use the configuration tag. And under configuration, we need the image tag, and to set the name of the image, we need to use the tag name. Now, I'm going to use my Docker Hub username, so that if I want, I can actually push the images to my Docker Hub registry. Okay? And the name of the image, then additionally, I also want to append the version of the project, which is project.version. And notice, this version is nothing but the one that you define in the project, like snapshot or any other version. The point is the name has to be consistent, and that's what we are doing so that anytime we are creating the image, it follows this pattern, the username, the name of the image, and whatever version that is currently active for the project. All right? So, let's reload it. Once the pom is ready, the next step is to run the plugin that we can do from here as well. So, if we just run the Maven plugin, it will now create the image for this application. So, if you run it for the first time, it will take a couple of minutes. So, let's wait, and I will come back. So, we can see that the plugin ran successfully, and it created the image with the name that we provided. The next step is to verify that the image exists, and the second step would be to run the container on top of this image and test the application endpoint that we defined in the controller. So, let's go to the terminal, and we will first see the image. So, if I run Docker images, and grab the pilot, then we can see that there is one image with the name that we provided. Okay? And we can find the metadata, like the ID and the size. So, now let's run the container and check the endpoint. So, we will use Docker run command, and the name of the image, this will now start the container based on the image that we created, and we can see that the application started successfully. So, what we can do, we can use the curl command to test the endpoint. If we go back, the end controller actually has this endpoint /api/demo. So, let's try to hit it now. And we can see the output here, that means the application is running as the container now. So, we successfully created the image using Spring Boot image plugin, and we successfully tested the container on top of that image. So, now this is complete, and we will move on to the step number two, which will be the Google Jib plugin. So, the good thing is Google Jib plugin is also similar to a Spring Boot image plugin. Both are Maven plugins. Okay? So, we just need to add the Maven plugin in the pom.xml, and same as Spring Boot image plugin, we just need to run the plugin. So, if we check out the documentation, the GitHub page of the Google Jib plugin, and here we will find all the details related to Google Jib. And here, we can see there are a couple of ways of running Google Jib plugin via Maven plugin, via CLI, Gradle plugin. We are interested in the Maven plugin, so let's check out the Maven plugin details. And here, we can find everything that we need on the plugin. So, let's go to the quick start, and you can see all it takes to run Google Jib is actually to configure this plugin, which is very similar to a Spring Boot Maven plugin. You can see the required artifact name and group ID, the version, and then the similar configuration tag. And here, we can see that the example shows how to, let's say, override the image. And essentially, that's what we were doing with Spring Boot image plugin. So, let's copy the code, and now we will try Google Jib. And this time, we will go to pom.xml. Let's comment this out, because we don't need this one. This was for Spring Boot image plugin. And now, we will add the new plugin. And please note that we don't need to actually delete this plugin. This is the Spring Boot Maven plugin, which is still required. We will simply add one more plugin, which is for Google Jib. And here, we need to to the name, so let's copy the same name that we were using earlier. The only difference is this time this will be created by Jib plugin. And to differentiate the images, I will add Jib to the image name. That's it. So, let's reload the palm. And now if we check under plugins, we should see the Jib. And we can see that the Jib plugin is available now. And it follows the same pattern. You simply run the plugin. Now, in case of Jib, this actually has two types of images. The one is without Docker daemon, and the second one is with Docker daemon. Since we are running the Docker daemon already, so I will run this version. So, let's run it. So, the image has been generated. It took around a minute for the plugin to create the new image. Once we have the image, we will first verify the Docker images command to see the image. Then we will run the container to test the endpoint. So, let's go to the terminal and verify the image. And we can see this one that we just created Google Jib. So, we will run the container again, but this time the image would be different. This time the image would be the Jib one. This will now try to start the container based on the image. And we can see that the server started fine. So, let's run the curl command again. And we can see the output also. So, this time also we can see that the server is working fine using the container. So, we successfully learned how to create the image using Google Jib plugin. Then we tested the application using the container. So, now let's move on and we will learn the DIY stuff, which is to create the images using the Dockerfile that we will write. So, before we start the DIY stuff, let's comment this plugin as well because we don't need this plugin anymore. This is Google Jib. So, here we have the file Dockerfile. And this is how we will create the image now. The good thing about Google Jib or Spring Boot image plugin is that they take care of everything when you create the image. All right? So, they do a lot of things out of the box. And we get many things out of the box. But the slight downside is you don't control the whole image creation process. So, in case when you are writing the Dockerfile, you have the full control on how do you want to create the images for your application. But then it becomes extremely important that we understand the whole process so that whatever we write in the Dockerfile, that follows the best practices. And so that we get the efficient image. Because in case of plugins, they apply all the best practices like layers, caching, security, standardization, everything. So, we don't have to worry about all those things. But when we are writing Dockerfile, we have to think about all those things. So, you can see in this Dockerfile, this is possibly the simplest Dockerfile possible for a Java application. So, you can see the base image. Then you can see the work DIR. Then it copies everything from the target to the app.jar, and then it runs the JAR file. So, when we have the Dockerfile, the next step is to create the image. And in this case, we create the image by running the Docker build command. So, we will first build the image, then we will run the image to run the container, and then we will test the endpoint. The same process all over again. So, let's go to the terminal and we will first build the image. To do that, we will use Docker build command. Let's tag the build. And this time we will give it a different name, pilot demo-diy. And the image has been created. So, let's verify by running the Docker images command as we were doing earlier. And you can see this is the image that we just created using the Dockerfile that we wrote. And if you see the difference, you can see this is very small, 92.5 MB only. And it depends on the base images as well because we did not configure the base images in Jib or Spring Boot image plugin. Hence we see larger size for the images created by them. But this time we are using the Alpine very simple minimal base image, and hence we can see the size is only 92.5 MB. All right? So, once we have the image, let's run the container and test the endpoint. So, we will do Docker run and the image. And we can see that the server started fine. So, let's test the endpoint by running the curl command. localhost Okay. So, we can see the output. That means the application is running fine as part of the container. Although we could see that this Dockerfile created a very small sized image, but the downside is this is a very straightforward Dockerfile. As we know Docker images have this concept of layers, different layers to utilize the caching to speed up the process. This particular Dockerfile is not using them. So, in the next example, that would be the Dockerfile multi-stage Dockerfile, we will see how can we actually split the process into different stages so that we have more layers so that we can utilize the caching. Now, we will not deep dive into this whole Docker thing. We assume since you know a little bit of Kubernetes, so you also know a little bit about Docker. So, we will just touch the concept. Hence we will just see an example of multi-stage builds. So, we have a file in here, Dockerfile.multistage. And if we open that, let me simply rename it so that we have the better color coding. So, now you can see the better color coding. All right? So, in the multi-stage builds, the idea is you split the process into different stages so that in the end when you generate the artifact or the image, that is that only has that you need. So, you can see that there is a build process, there is a build stage, then there is this runtime stage. In this stage, we are doing whatever we need to build the artifact. So, you can see that the work DIR was defined, then you copied the pom.xml, the Maven executable, then you ran the command dependency go offline, then you copied the source folder, and then you ran the command yourself to package the artifact. While in this case, this Dockerfile assumes a JAR file. So, that means there must be another process which packages the application and generates the JAR first. But in this case, the build phase guarantees that by the end you will have an artifact. That means the JAR file. All right? Then once we have the JAR file, the runtime stage is then using the same image that we were using earlier, and actually create Sorry, the copying the JAR file to the work directory, and then running the executable command. So, this is more or less the same thing, at least the runtime part. But the new thing is it has a build stage. So, it utilizes the caching and the layers in a better way. For example, in case there is no change in the dependencies, then there will be no need to run this command again, and the Docker runtime can actually use the same layer. So, better caching. In the same way, let's say there is no change in the source folder, then also it doesn't need to change anything. It can simply use the same layer. So, the point that we need to understand is while writing the Dockerfile gives the full control to the developer, but it also brings the responsibility of understanding the whole process. The point is when you write the Dockerfile yourself, you need to understand each and every bit. And we must ensure that we follow all the best practices so that this image creation process is efficient and effective. Now, we will not test this Dockerfile because it follows exactly the same process, the DIY stuff. So, if you want to test this Dockerfile, you will simply run the same build command to create the new image. Then you will run the same Docker run command. So, we will not run this one for the demo. We will simply move on to the comparison part or the summary part. All right, let's move on. So, now that we have covered all the four different ways to generate the Docker images, it's a good time to summarize everything. So, if you want the low effort and potentially the smallest image size, then we can go with the DIY Dockerfile stuff. Because as we saw, when we write the Dockerfile itself, depending on the base images, it can actually generate a very minimal, very small image. That is the good thing about Dockerfile along with that you have the full control. The thing about Google Jib is that it gives you a better performance. The whole image creation process is extremely fast, and it puts more focus on the developer efficiency aspect in the whole process. You get all those things out of the box with Google Jib plugin. The good thing about Spring Boot image plugin is that it is very customized for Spring Boot applications. So, because this is directly coming from Spring Boot, so that plugin understands the whole Spring Boot process, and we get the benefit of that Spring policy in this process. So, the good thing about Spring Boot image plugin is that it puts more focus on the standardization and the security aspect of images. So, if that's important for you, especially the security part, then feel free to adopt the Spring Boot image plugin. And in the end, we have the multi-stage Dockerfile, which is an example of the balanced approach where you have the full control on how you create the images, but you also put focus on the efficiency part. So, that completes the first video in which we learned different ways to create the images for the Spring Boot applications. Now, for the learning, it doesn't matter which option you pick. You can pick any of these four or something else. As long as you have the container image, you can do or you can follow the steps in the future videos to actually deploy the application on Kubernetes. So, we will wrap this video now. And in the next video, we will start learning Kubernetes, how to deploy these applications. So, thanks for watching, and I will see you in the next video. >> [music]

Original Description

Github repo - https://github.com/therealdumbprogrammer/spring-boot-image-demo/tree/master We begin with the most important foundation: building a production-ready Docker image for a Spring Boot application. Instead of a basic Dockerfile, we focus on: Creating optimized, smaller images Using multi-stage builds Running containers as non-root Structuring images for better caching and faster deployments Understanding why container design directly impacts Kubernetes behavior This video sets the stage for everything that follows — because Kubernetes doesn’t run your code, it runs your container. ⏱️ Timestamps 00:00 – Intro 01:15 – Why containers? 03:46 – Spring Boot Image Plugin 08:30 – Google Jib Plugin 11:26 – DIY Dockerfile 15:02 – Multi-stage Dockerfile 17:35 – Summary #SpringBoot #Kubernetes #SpringBootDocker #SpringBootOnKubernetes #KubernetesLocalSetup #SpringBootBuildImage #JavaDevelopers #SpringBootTutorial #KubernetesForJava #CloudNative #JavaMicroservices
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Related Reads

📰
Receipts, not labels: what cron trust hand-offs get wrong about provenance
Learn why cron trust hand-offs fail with labels and how receipts can improve provenance
Dev.to · Aloya
📰
Mastering Terraform Interviews (2026 Edition): Interview Questions & Answers from Beginner to…
Master Terraform interviews with questions and answers for all levels, from beginner to advanced, to boost your DevOps career
Medium · DevOps
📰
How I Balance Developer Velocity With Security Requirements
Learn how to balance developer velocity with security requirements in DevSecOps
Medium · DevOps
📰
How WLOADCTL Enables Real-Time Monitoring for Enterprise Batch Workloads
Learn how WLOADCTL enables real-time monitoring for enterprise batch workloads, improving workload management and efficiency
Dev.to · weeli

Chapters (7)

Intro
1:15 Why containers?
3:46 Spring Boot Image Plugin
8:30 Google Jib Plugin
11:26 DIY Dockerfile
15:02 Multi-stage Dockerfile
17:35 Summary
Up next
How to Code with Distrobox on the Steam Deck
Ian Wootten
Watch →