All right.
We did some pretty solid work with the flask app.
Now, you know what I'm going to do is Docker system, prune dash a, remove everything, start from
a clean slate.
Because now we're going to containerize a spring boot application.
Let me just make sure we're all good.
Containers are gone.
Images are gone.
All right let's have some fun.
So let us go inside of the main.
I thought the instructions would have been in the main class, but apparently they're here.
I must have misplaced them or the developer must have misplaced them.
Anyways, they're telling us that here are a few ways to get the Spring Boot app up and running.
Assuming a bare metal setup, no docker containers or anything so we can use Maven.
Maven is a build tool that relies on a Java development kit in order to run, uh, to install dependencies
and run the app all in one single command.
Maven clean Spring Boot Run option two of running this app is to use Maven to install the dependencies
first, and then run the app.
So you can see that our Docker file is going to be uh, is going to be different if we choose option
two as opposed to option one better in my opinion.
And option three is to package up the image is to package up the spring boot application into a Jar
file, and then instead of using Maven to run the resulting Jar file, we use a simple Java command.
So that's going to have effects on our Docker file as well.
So depending on which option we choose to run and build the application, we need to dockerize our application
differently.
All right.
So let us start by actually you know what before we start, I want to.
I want to go here.
So here what we're going to do is we're going to pull an image that combines, uh, a maven as well
as an open JDK runtime.
We need Maven as well as Java in order to run a spring boot application.
If you're a spring boot developer, you or if you've taken my Spring Boot course, you would know that
you need Maven and Java to run a Spring Boot app.
Depending on which type of app you're running, you need different types of environments.
All we going to do is pull that preconfigured environment as a base image into our overall image that
is going to also contain, uh, the application itself and as well as any dependencies that the application
relies on in order to run.
Now, notice that our overall image doesn't also include the dependencies.
Why this command is going to install any dependencies that the application relies on.
If the dependencies aren't already there.
In this case, they are not going to be in our Docker image and then it's going to run our application.
The flaw with relying on this approach is that now the container is going to take a really long time
to load the application, because it needs to install the dependencies that should have been present
already in the Docker image.
It needs to install the dependencies inside the container itself so that the application we run has
access to them.
All right, enough talking.
Let's just get to work.
So from base image, the image that we need to call that we need to pull must combine an environment
of Maven and Java.
So let me go to Maven.
Okay.
This is the official repo for all sorts of images.
For Maven I want one that combines Maven and OpenJDK.
Uh, the image shows us OpenJDK seven.
The schematic here shows OpenJDK 17.
Maven 3.8.
So let's just find something that matches it.
Uh 3.8 OpenJDK 17.
Maybe we can write it.
Let's try.
Open JDK 17 slim.
So we've got 3.853.8.
Beautiful.
I'm just going to copy this over.
So remember the repo is Maven followed by a colon.
We specify the tag.
It should autocomplete anyway.
So we're going to say Maven followed by open JDK.
Um let me just paste it.
Yep that's what we want.
Now we set the working directory inside the container.
Uh we're going to load our application inside the working directory slash app.
The project files that we're going to copy is everything inside of Spring Boot demo.
So I'm going to copy everything inside of Spring Boot demo into the working directory.
Remember, after step two, everything happens inside the working directory.
After we copy spring boot demo into the working directory, we need to inform the developer that the
application is using container port 8080.
Um, okay.
So we just say expose port 8080.
Whoever is running the container, please expose port 8080 to the outside world.
Define the command to run when the container starts.
When the container starts, we need to tell it to execute the command Maven clean spring boot run.
So clean is going to remove the target folder if the dependencies aren't already there, which they
won't be.
It's going to reinstall them during the runtime, which is not good.
The dependencies should already be present during the build process, but in this case, when the container
starts, it's going to clean the target folder, install the dependencies that the application relies
on, and then it's going to run the application.
Not not good.
Anyways, we're going to say we're going to CD out of five starter code.
We're going to clear the output.
We're going to CD into oh six starter code.
Then I'm going to say Docker build T.
Um, one more thing I want to mention.
Uh, Maven Clean spring boot run only works if the container is already pointing at the root directory
of the project itself.
So that's why it's important that we copy the contents of spring boot demo into the working directory,
not the folder itself.
Because if the container just sees a folder of spring boot demo, this command isn't going to work.
It needs to see a pom.xml file for it to start the build process.
That's just how Spring Boot works.
Um, so you need to make sure that we copy the contents of Spring boot demo into the working directory,
not the the the whole folder.
Anyways, docker build t, we're going to call the image spring boot demo, and we're going to build
an image from the docker file in the current directory.
Oh six starter code.
The Maven 3.8 open JDK image is quite large, which is why it took 5.5 seconds for it to load.
And now notice when we, uh, create a container.
So docker run, um, we're going to map The container port 8082.
A host machine port of 8080.
We're going to set the container to remove when we're done with it.
We're going to call the container spring boot demo container.
We are going to create a container from the image spring boot demo.
Are we missing anything?
I don't think so.
When we create the container it's going to run this command.
And the command is going to start by installing all the dependencies that the application relies on
in order to compile, and only after installing the dependencies then it's going to run the application.
This is simply how this spring boot command works.
If it doesn't find all the dependencies that are listed in the Pom.xml, it's going to install them
and then run the app.
That's the maven lifecycle.
And the runtime took quite a long time, which is not good.
Typically, you want your app to run right away.
Imagine you have a large amount of users that are relying on your application to be readily available.
Let's say the application fails for whatever reason.
You want that container to restart right away.
You don't want it to take its time installing dependencies.
That's why we are going to stop this runtime control.
See, that didn't work.
Let's try control Z.
All right.
It worked out.
That's why we are going to rely on option number two.
We want to run Maven install during the image building phase.
That way the dependencies are installed inside of the image.
And then when we run Maven Spring Boot run it's already going to see it's already going to have access
to all these dependencies.
So it can just go ahead and run the application right away.
So going over to the schematic this time we are going to run this command during the image building
phase.
That's going to install all the dependencies that spring boot demo relies on in order to run.
Then if we provide the container with this command, it's going to be able to run the application right
away, because the dependencies listed in the Pom.xml are already there, they're already present,
they've already been installed.
So here we are optimizing our Docker image for optimal runtime.
Okay, after we copy over all of the project files, then what we're going to do is install the dependencies
listed listed inside of Pom.xml.
So you know how in Python, uh, the dependencies are listed in requirements.txt, uh, for a maven
spring boot app there in a pom.xml file.
So the things some things differ a little bit, but in the end they're all inherently quite the same.
If you as the DevOps captain, if you talk to your developers, you ask them, hey, where is the file
that has the dependencies?
How do you run this app and all that?
Then you can make informed decisions on how you're going to create the image, how you're going to create
the container.
So you don't necessarily have to be a spring boot master.
You just need to talk to the developers of the app to know what the moving parts are and how you, as
the Docker guy, the DevOps guy, are going to manipulate them.
So here we're going to run a command during the image building phase that installs what was the command.
Again, let's just be consistent with what's being given to us.
We're going to run a command that installs the dependencies present inside of the pom.xml file.
So again, I want to emphasize the importance of the Pom.xml file being directly present inside the
working directory so that when we run Maven install, it automatically sees Pom.xml file Pom.xml.
Inside, the Workdir is able to successfully install the dependencies, and then if we run Maven Spring
boot run, it will already see the dependencies and run the application right away.
So let us rebuild, uh, the image.
And now you can see it's installing all the dependencies during the image building phase, so that when
we create the container, it's able to run the app right away.
Pretty cool.
So once you.
So once because the developer was so, um, helpful in giving us the different ways that this app can
be run.
It helped us make better informed decisions about how we should run the app within our container.
Because now let's imagine I pushed this image onto Docker Hub, and I'm ready to create a container
that runs it.
The container is going to be able to run it right away.
So docker build t dash spring boot demo.
Let's just reuse the command from earlier.
It ran it right away.
It already detected all the dependencies and we were good to go.
So if we go to localhost 8080.
Wonderful.
All right.
Now there's actually a third.
Excuse me.
There's actually a third option, uh, given to us to run the app.
We can use Maven to package the application.
And it's the and its dependencies into a self-contained Jar file.
Then we can run the Jar file using Java jar.
All right.
So here what I can do is say run maven package.
What that's going to do is install the dependencies.
It's going to build the source code.
And it's going to combine everything into a self-contained Jar file.
So after we run Maven package we can just say over here Java dash jar.
And now let's just go ahead and copy over the remaining command.
So all we need is the command to run the code.
And we can set that up inside of our Docker file.
So now.
Um I'm going to rebuild.
I'm going to rebuild our image.
Here you can see Maven package is downloading all the dependencies.
It's going to build our code, and the resulting Jar file is going to package up the source code as
well as the dependencies, which means we can just run it using a simple Java jar command afterwards.
It's taking quite some time to do so.
All right.
Now I'm going to say Dot, let's just reuse the one from before unable to access jar file Demo1 dash
snapshot jar.
There seems to be an issue.
How are we going to troubleshoot this issue?
Worry not.
We have complete transparency over what's happening inside the working directory.
So this is a very useful tool to troubleshoot.
I recommend you get used to it.
Starting up an interactive shell inside of your container to know exactly what's happening in it.
Uh.
Dash it.
Um, you know what?
I can already see what the mistake is, but, um, whatever.
Let's just do RLS.
So here we have Maven Pom.xml source and the target folder.
Exactly what was copied over the jar file is actually present inside of the target folder itself.
So if I do CD target and then RLS target slash demo oh one snapshot jar.
So when when it's at the working directory it didn't see the jar file.
It saw a target folder.
And then inside the target folder is where the jar file is.
So I made a mistake of not reading the full instruction.
Sorry guys, I feel like I'm talking too much, but I just want to make sure that you guys get everything
that's going on.
So now if I rebuild the image so that we give the container the proper command, everything should work
smoothly.
Beautiful.
When you've already got the jar file set up, prepackaging everything the code's already compiled,
you just run Java jar.
The container started very fast, starting up the container running just a simple jar file as opposed
to running Maven spring boot run with the other one.
So Maven Spring Boot Run has to build and actually compile.
Then run the application code based on the dependencies that are provided.
That took a much longer time than just running a jar file where everything was already built and prepackaged.
All right, guys, that's pretty much it.
Now we're going to move on to source code number seven.
I'll see you in the next one.