Enterprise Java with Spring Boot

Build & Run Spring Boot with Docker

Josh Long
Broadcom
Enterprise Java with Spring Boot

Lesson Description

The "Build & Run Spring Boot with Docker" Lesson is part of the full, Enterprise Java with Spring Boot course featured in this preview video. Here's what you'd learn in this lesson:

Josh walks through running a Spring app inside a Docker container. Through Docker virtualization, binaries for other operating systems can be generated with minimal configuration. Data sources can also be quickly created within a container, allowing for easier connection configuration.

Preview
Close

Transcript from the "Build & Run Spring Boot with Docker" Lesson

[00:00:00]
>> Josh Long: We have a sample application that we built in the intro and that sample application, I showed you both how to run it. I ran it from within the IDE. I right clicked on it and I chose debug or run or whatever. And that'll run in your local IDE.

[00:00:14]
I've got the port being blocked. Let me shut down that. Where is actually that port over here surely. Yeah, so I can run in the IDE like that, right? And make sure that when you're running it, make sure you have the green spring leaf, not the regular Java one.

[00:00:30]
This is just a regular Java process. IntelliJ has some badging. It's like a facet or whatever. It'll detect that you're using a spring app and it'll run things a little bit more quickly that way. Okay, so that's on the IDE. But if I just want to test on the command line, if want to like know for sure it's working, go to your code and CD service and I'm going to do maven spring boot run.

[00:00:59]
Let me stop this over here. And then that'll run it on the JRE on your local machine, as you'd expect. Now that's on the jre, I've got this JVM application. It's on the JRE like I said. And I showed you this, the self contained jar. But that still requires a jvm, right?

[00:01:19]
So DU minus HS service blah jar. This is not what you would normally get if you compiled the jar. Because we only wrote like 10 lines of code, right? It's whatever. The source code that we contributed to the project was not even a kilobyte, basically. And yet this jar is 27 megs.

[00:01:38]
And that's because it contains everything you need to run the program, except for the JRE itself. Then I turned it into a native image and then it contained everything it needed to run the program. Including the jre, right? Including the runtime in that native binary. And that native binary was a full 75, no, 90 megs.

[00:01:55]
So yeah, quite a bit bigger, right? 63 megs bigger than without. So that 63 megs will be the JRE that gets packaged in the native binary. That native binary is macOS specific. It does not run, it's not write once run anywhere. It only works on Mac and when you compile it on Windows you get service exe and guess what?

[00:02:16]
It'll only run on Windows. When you compile it on Linux, guess what? It'll run on Linux. One of the things that's really nice about that is that you can also build a Docker image out of this project. So Maven Spring Boot build image. So I'm going to run that and then let it do its thing in the background behind the scenes.

[00:02:43]
That's going to use buildpacks and buildpacks will actually dockerize my image for me. Buildpacks are. There you go. Buildpacks are a technology that was originally created by the folks at Heroku. Have you heard of Heroku? It's a platform as a service. They created it back in 2008. They made originally they were a platform specifically for Ruby on Rails apps and eventually they migrated towards sort of cross language polyglot runtimes.

[00:03:18]
And to support that they needed a little bit of indirection between the bit that actually runs the program and the bit that you upload. So when you upload something to Heroku, how do they then know to run it? Well, they need to standardize. They need to have a set of standardized scripts that know how to run a given source code repository, right?

[00:03:36]
So if it's a Java workload versus a Ruby on Rails workload versus a Python workload versus a PHP versus whatever, they need to have a standardized set of hooks to call. So they created this buildpack concept. I work at Broadcom, we have a distribution called Cloud Foundry. Cloud Foundry is.

[00:03:53]
We have a product called Tanzu Application service based on something called Cloud Foundry. Cloud Foundry is an open source platform platform as a service, very much in the style and the spirit of Heroku. And because that was a good idea, these buildpacks are such a good idea, we pulled these things in, we pulled in buildpacks as well.

[00:04:12]
And so buildpacks are actually something that we both separately innovated on. And then eventually for version 3.0 of the technology, we worked together. So we actually released version three of BuildPacks. And you can actually find information about BuildPacks here. BuildPacks IO, Cloud Native BuildPacks. And these are basically container first recipes for turning an arbitrary workload, be it a Java application or Python or NET or COBOL or Next JS or whatever.

[00:04:43]
And turning it into a container that you can then run. If you're using that, you can use it. There's a pack CLI that you can use. But I just did this. I used the spring boot plugin, spring boot build image and I got this Docker image here. So I can do Docker run and there's the application.

[00:05:06]
So I've already Got the port. I don't have the right. It's not going to connect to postgres because it's inside of local host in my Docker image is not the same as my Mac OS Hosting port. So minus e spring data source URL equals jdbc PostgreSQL local. Sorry, it's what is it?

[00:05:32]
A host.docker.Internet my database, I think, 8080: 8080. Is that the right port? Looks like it. Okay, so now if I go to localhost customers. Yeah, there you go. So I ran this Docker image, this Docker image I generated from buildpacks. Did you all see that? I used spring boot build image.

[00:06:03]
It built a Docker image for me out of my application. I then ran it on my local machine and I had to override the environment variable, the property spring data source URL. I overrode it by pointing it to host.docker.Internet which is the host of my Mac relative to the container running on my Mac, which is running inside of a virtual machine.

[00:06:24]
Okay, so that should be very easy. Getting a dockerized image out of your source code should not be a thing. This should not be a problem. If you spend more than one second trying to make that work, you spend too long. It's built in your production worthy out of the box, so you can focus on other things.

[00:06:43]
You can also build a native image. So I go over here, let's see. Do that again. Remember, I built a native image on the local Mac, but if you want this Docker image to have that native image, then you have to enable this so P native. And that will take a fair bit longer.

[00:07:00]
But what that's going to do is it's going to compile in my Docker image. It's going to compile the native image and then package that native Linux binary in the Docker image, even though I'm running on a Mac. So it's going to do the compilation in the Docker virtual machine on Linux.

[00:07:17]
So then the resulting binary will be Linux as well. So now I'll have something I can deploy to any container registry, and it'll run anywhere that Linux is. It will work. So this will take a fair bit longer. Remember that native image compilation takes a lot longer than just regular JVM runs.

[00:07:36]
Okay, so that Docker image is built, right? That took a minute, a whole minute to build a Docker image that has native code inside of it though, right? So if I run this Docker run that starts up Same issue as before, though. So here we go. That starts up in 75 milliseconds.

[00:07:54]
So keep in mind what just happened. I built a native image inside of a Docker image, ran it on my Mac. Remember, behind the scenes, Docker is using virtualization to simulate Linux and then inside Linux, I did the compilation. And then I'm inside that Linux emulation, I'm running Java, I'm running the native binary.

[00:08:18]
The native binary inside of Linux on my Mac start up in 75 milliseconds, whereas the native binary on my Mac directly started up in point. What was it, 9 or something like that? 0.8. It's actually faster. The Linux compilation. The native image compilation you get on Linux is actually amazingly fast.

[00:08:35]
It's much faster than the native one on Mac OS for me at least. So you might be surprised to actually have better performance on Linux, even though you've presumably got a much better laptop than you do in production. Your machine's low, your machine for your desktop is better.

[00:08:53]
Okay, so that's how to get. That's how to get. I want you to know, graalvm, Docker, these two things, they are your tools for building and producing images that go to production. When I say Docker, one of the things that people always ask about is, how do I build applications and support that git clone run life if I need a postgres or whatever?

[00:09:16]
Well, you saw me do it earlier, you saw me go to start Spring IO and I can choose Docker Compose support. There's another thing I can choose, which is test containers support. So I'm going to add postgres here again. So this is, I'm going to close the old example down here.

[00:09:33]
This is not running anymore. Closing that and we're going to hit Enter CD Downloads UAO demo. Okay, so you can see what has happened is that the Spring initializer generated this Docker compose file for postgres and it'll do that for a lot of things if you do MySQL let's see if it does that.

[00:09:57]
If I go, by the way, control space on Start Spring IO lets you explore the files that will get generated. So there you go. You can see, actually there's Postgres and MySQL at the top. What about Neo4j? Or what about MongoDB? If I go over here, there's MongoDB, Atlas, the Vector Store, there's MySQL there's Neo4j, what about Redis?

[00:10:23]
Go over here again and there's Redis. So you can see it's pretty helpful if you really want to. If you like Cert Spring, that is not just a great way to build a new Spring project. It can be a really great way to get some test images for all these different data stores you might want to use up and running.

[00:10:38]
So I went to Start Spring IO. I had chose control space. I can explore, compose YAML, I can copy and paste that. I'm adding infrastructure to my build and it's automatically giving me these Docker containers that I can run to start up a test local. MongoDB, MySQL, Neo4j, Postgres, Redis, etc.

[00:10:58]
I did that over here in my brand new project Start Spring IO. And when I did that, it added some dependencies to the build. Docker Compose, right? It also added test containers. So these two things are very important when we start the Spring boot application. When I start the Spring boot application with the Docker Compose support, remember in this Docker compose file, I have not exposed, I have not exported the port, right.

[00:11:21]
The port is just local. But I've got a Docker image here for postgres. Okay, so let's go back to this. I'll say Docker PS minus a Docker RM F and then take that Docker ps. There's no Docker images running here. So now I'm going to run this application and remember how quickly these things start up normally.

[00:11:42]
But I've left this Docker Compose support here. Docker Compose. Okay, that's there. Let's run this application. No changes to the code whatsoever. You can see it took forever to start up because it actually started up the Docker file for me. But the result is that that took almost twice as long, four times as long as it would normally to start it up.

[00:12:08]
This is quite convenient because now during my development time, if I go over here, Docker ps, you can see I've got Postgres running. My applications are already connected to it.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now