WEBVTT

00:00.290 --> 00:00.830
All right.

00:00.830 --> 00:03.920
We did some pretty solid work with the flask app.

00:03.920 --> 00:11.240
Now, you know what I'm going to do is Docker system, prune dash a, remove everything, start from

00:11.240 --> 00:12.440
a clean slate.

00:12.440 --> 00:16.760
Because now we're going to containerize a spring boot application.

00:16.790 --> 00:18.380
Let me just make sure we're all good.

00:18.380 --> 00:19.310
Containers are gone.

00:19.310 --> 00:20.900
Images are gone.

00:20.930 --> 00:25.430
All right let's have some fun.

00:25.430 --> 00:33.830
So let us go inside of the main.

00:34.070 --> 00:38.120
I thought the instructions would have been in the main class, but apparently they're here.

00:38.120 --> 00:41.780
I must have misplaced them or the developer must have misplaced them.

00:41.780 --> 00:47.240
Anyways, they're telling us that here are a few ways to get the Spring Boot app up and running.

00:47.270 --> 00:53.120
Assuming a bare metal setup, no docker containers or anything so we can use Maven.

00:53.120 --> 01:00.620
Maven is a build tool that relies on a Java development kit in order to run, uh, to install dependencies

01:00.620 --> 01:03.320
and run the app all in one single command.

01:03.350 --> 01:10.730
Maven clean Spring Boot Run option two of running this app is to use Maven to install the dependencies

01:10.730 --> 01:12.860
first, and then run the app.

01:13.190 --> 01:19.430
So you can see that our Docker file is going to be uh, is going to be different if we choose option

01:19.430 --> 01:23.630
two as opposed to option one better in my opinion.

01:23.630 --> 01:30.290
And option three is to package up the image is to package up the spring boot application into a Jar

01:30.290 --> 01:38.240
file, and then instead of using Maven to run the resulting Jar file, we use a simple Java command.

01:38.240 --> 01:41.270
So that's going to have effects on our Docker file as well.

01:41.270 --> 01:50.120
So depending on which option we choose to run and build the application, we need to dockerize our application

01:50.120 --> 01:51.110
differently.

01:51.620 --> 01:52.310
All right.

01:52.310 --> 01:59.670
So let us start by actually you know what before we start, I want to.

01:59.820 --> 02:01.050
I want to go here.

02:04.350 --> 02:12.180
So here what we're going to do is we're going to pull an image that combines, uh, a maven as well

02:12.180 --> 02:14.070
as an open JDK runtime.

02:14.070 --> 02:20.280
We need Maven as well as Java in order to run a spring boot application.

02:20.280 --> 02:24.900
If you're a spring boot developer, you or if you've taken my Spring Boot course, you would know that

02:24.900 --> 02:27.210
you need Maven and Java to run a Spring Boot app.

02:27.210 --> 02:31.110
Depending on which type of app you're running, you need different types of environments.

02:31.140 --> 02:37.140
All we going to do is pull that preconfigured environment as a base image into our overall image that

02:37.140 --> 02:44.040
is going to also contain, uh, the application itself and as well as any dependencies that the application

02:44.040 --> 02:45.600
relies on in order to run.

02:45.630 --> 02:51.210
Now, notice that our overall image doesn't also include the dependencies.

02:51.240 --> 02:56.610
Why this command is going to install any dependencies that the application relies on.

02:56.610 --> 02:58.980
If the dependencies aren't already there.

02:58.980 --> 03:04.530
In this case, they are not going to be in our Docker image and then it's going to run our application.

03:04.560 --> 03:12.270
The flaw with relying on this approach is that now the container is going to take a really long time

03:12.270 --> 03:17.880
to load the application, because it needs to install the dependencies that should have been present

03:17.880 --> 03:19.680
already in the Docker image.

03:19.680 --> 03:25.470
It needs to install the dependencies inside the container itself so that the application we run has

03:25.500 --> 03:26.880
access to them.

03:26.910 --> 03:28.200
All right, enough talking.

03:28.200 --> 03:29.100
Let's just get to work.

03:29.100 --> 03:37.290
So from base image, the image that we need to call that we need to pull must combine an environment

03:37.290 --> 03:38.880
of Maven and Java.

03:38.880 --> 03:41.220
So let me go to Maven.

03:42.990 --> 03:43.770
Okay.

03:43.770 --> 03:47.490
This is the official repo for all sorts of images.

03:47.490 --> 03:52.860
For Maven I want one that combines Maven and OpenJDK.

03:53.280 --> 03:56.040
Uh, the image shows us OpenJDK seven.

03:56.850 --> 03:59.100
The schematic here shows OpenJDK 17.

03:59.100 --> 03:59.910
Maven 3.8.

03:59.910 --> 04:01.890
So let's just find something that matches it.

04:02.580 --> 04:06.600
Uh 3.8 OpenJDK 17.

04:06.660 --> 04:08.250
Maybe we can write it.

04:09.360 --> 04:10.890
Let's try.

04:10.920 --> 04:15.090
Open JDK 17 slim.

04:17.430 --> 04:19.770
So we've got 3.853.8.

04:19.800 --> 04:20.580
Beautiful.

04:20.580 --> 04:22.470
I'm just going to copy this over.

04:22.470 --> 04:26.190
So remember the repo is Maven followed by a colon.

04:26.190 --> 04:27.630
We specify the tag.

04:27.630 --> 04:29.040
It should autocomplete anyway.

04:29.040 --> 04:34.950
So we're going to say Maven followed by open JDK.

04:35.970 --> 04:37.410
Um let me just paste it.

04:40.890 --> 04:42.840
Yep that's what we want.

04:42.870 --> 04:45.840
Now we set the working directory inside the container.

04:45.930 --> 04:51.660
Uh we're going to load our application inside the working directory slash app.

04:52.530 --> 04:58.470
The project files that we're going to copy is everything inside of Spring Boot demo.

04:58.470 --> 05:08.490
So I'm going to copy everything inside of Spring Boot demo into the working directory.

05:08.520 --> 05:13.020
Remember, after step two, everything happens inside the working directory.

05:13.110 --> 05:19.110
After we copy spring boot demo into the working directory, we need to inform the developer that the

05:19.110 --> 05:22.680
application is using container port 8080.

05:23.610 --> 05:25.290
Um, okay.

05:25.320 --> 05:28.110
So we just say expose port 8080.

05:28.140 --> 05:33.090
Whoever is running the container, please expose port 8080 to the outside world.

05:33.090 --> 05:36.450
Define the command to run when the container starts.

05:36.450 --> 05:47.370
When the container starts, we need to tell it to execute the command Maven clean spring boot run.

05:47.370 --> 05:53.530
So clean is going to remove the target folder if the dependencies aren't already there, which they

05:53.530 --> 05:54.220
won't be.

05:54.250 --> 05:58.450
It's going to reinstall them during the runtime, which is not good.

05:58.480 --> 06:03.940
The dependencies should already be present during the build process, but in this case, when the container

06:03.940 --> 06:09.400
starts, it's going to clean the target folder, install the dependencies that the application relies

06:09.400 --> 06:11.620
on, and then it's going to run the application.

06:11.620 --> 06:13.270
Not not good.

06:13.300 --> 06:17.650
Anyways, we're going to say we're going to CD out of five starter code.

06:17.650 --> 06:19.870
We're going to clear the output.

06:19.870 --> 06:25.090
We're going to CD into oh six starter code.

06:26.770 --> 06:30.250
Then I'm going to say Docker build T.

06:31.660 --> 06:34.690
Um, one more thing I want to mention.

06:35.020 --> 06:43.210
Uh, Maven Clean spring boot run only works if the container is already pointing at the root directory

06:43.210 --> 06:44.830
of the project itself.

06:44.830 --> 06:50.200
So that's why it's important that we copy the contents of spring boot demo into the working directory,

06:50.230 --> 06:51.760
not the folder itself.

06:51.760 --> 06:57.160
Because if the container just sees a folder of spring boot demo, this command isn't going to work.

06:57.160 --> 07:02.710
It needs to see a pom.xml file for it to start the build process.

07:02.710 --> 07:04.420
That's just how Spring Boot works.

07:04.420 --> 07:10.000
Um, so you need to make sure that we copy the contents of Spring boot demo into the working directory,

07:10.030 --> 07:13.210
not the the the whole folder.

07:13.330 --> 07:21.970
Anyways, docker build t, we're going to call the image spring boot demo, and we're going to build

07:21.970 --> 07:24.190
an image from the docker file in the current directory.

07:24.220 --> 07:26.170
Oh six starter code.

07:29.770 --> 07:38.680
The Maven 3.8 open JDK image is quite large, which is why it took 5.5 seconds for it to load.

07:38.710 --> 07:43.240
And now notice when we, uh, create a container.

07:43.510 --> 07:52.240
So docker run, um, we're going to map The container port 8082.

07:52.270 --> 07:54.400
A host machine port of 8080.

07:55.330 --> 07:57.910
We're going to set the container to remove when we're done with it.

07:57.940 --> 08:02.320
We're going to call the container spring boot demo container.

08:02.590 --> 08:07.660
We are going to create a container from the image spring boot demo.

08:09.190 --> 08:10.330
Are we missing anything?

08:10.330 --> 08:11.020
I don't think so.

08:11.020 --> 08:14.560
When we create the container it's going to run this command.

08:14.560 --> 08:21.640
And the command is going to start by installing all the dependencies that the application relies on

08:21.640 --> 08:28.540
in order to compile, and only after installing the dependencies then it's going to run the application.

08:28.540 --> 08:31.390
This is simply how this spring boot command works.

08:31.390 --> 08:37.720
If it doesn't find all the dependencies that are listed in the Pom.xml, it's going to install them

08:37.720 --> 08:39.220
and then run the app.

08:39.220 --> 08:42.100
That's the maven lifecycle.

08:42.520 --> 08:47.350
And the runtime took quite a long time, which is not good.

08:47.380 --> 08:50.890
Typically, you want your app to run right away.

08:50.920 --> 08:57.430
Imagine you have a large amount of users that are relying on your application to be readily available.

08:57.460 --> 09:00.880
Let's say the application fails for whatever reason.

09:00.880 --> 09:03.130
You want that container to restart right away.

09:03.130 --> 09:06.490
You don't want it to take its time installing dependencies.

09:06.490 --> 09:11.920
That's why we are going to stop this runtime control.

09:11.950 --> 09:12.430
See, that didn't work.

09:12.460 --> 09:14.230
Let's try control Z.

09:15.070 --> 09:15.550
All right.

09:15.580 --> 09:16.540
It worked out.

09:17.200 --> 09:22.300
That's why we are going to rely on option number two.

09:22.780 --> 09:28.690
We want to run Maven install during the image building phase.

09:28.720 --> 09:32.770
That way the dependencies are installed inside of the image.

09:32.770 --> 09:38.770
And then when we run Maven Spring Boot run it's already going to see it's already going to have access

09:38.770 --> 09:40.420
to all these dependencies.

09:40.420 --> 09:44.110
So it can just go ahead and run the application right away.

09:44.140 --> 09:53.080
So going over to the schematic this time we are going to run this command during the image building

09:53.110 --> 09:53.950
phase.

09:53.950 --> 09:59.020
That's going to install all the dependencies that spring boot demo relies on in order to run.

09:59.020 --> 10:05.680
Then if we provide the container with this command, it's going to be able to run the application right

10:05.680 --> 10:12.100
away, because the dependencies listed in the Pom.xml are already there, they're already present,

10:12.100 --> 10:14.080
they've already been installed.

10:14.080 --> 10:21.910
So here we are optimizing our Docker image for optimal runtime.

10:22.630 --> 10:31.000
Okay, after we copy over all of the project files, then what we're going to do is install the dependencies

10:32.050 --> 10:37.270
listed listed inside of Pom.xml.

10:37.270 --> 10:43.810
So you know how in Python, uh, the dependencies are listed in requirements.txt, uh, for a maven

10:43.810 --> 10:47.140
spring boot app there in a pom.xml file.

10:47.140 --> 10:53.680
So the things some things differ a little bit, but in the end they're all inherently quite the same.

10:53.710 --> 10:59.260
If you as the DevOps captain, if you talk to your developers, you ask them, hey, where is the file

10:59.260 --> 11:00.370
that has the dependencies?

11:00.370 --> 11:02.140
How do you run this app and all that?

11:02.140 --> 11:07.930
Then you can make informed decisions on how you're going to create the image, how you're going to create

11:07.930 --> 11:09.070
the container.

11:09.070 --> 11:12.760
So you don't necessarily have to be a spring boot master.

11:12.760 --> 11:18.700
You just need to talk to the developers of the app to know what the moving parts are and how you, as

11:18.700 --> 11:21.910
the Docker guy, the DevOps guy, are going to manipulate them.

11:21.910 --> 11:30.730
So here we're going to run a command during the image building phase that installs what was the command.

11:30.730 --> 11:34.510
Again, let's just be consistent with what's being given to us.

11:36.370 --> 11:43.310
We're going to run a command that installs the dependencies present inside of the pom.xml file.

11:43.550 --> 11:52.940
So again, I want to emphasize the importance of the Pom.xml file being directly present inside the

11:52.940 --> 12:00.590
working directory so that when we run Maven install, it automatically sees Pom.xml file Pom.xml.

12:00.590 --> 12:06.650
Inside, the Workdir is able to successfully install the dependencies, and then if we run Maven Spring

12:06.650 --> 12:13.460
boot run, it will already see the dependencies and run the application right away.

12:13.580 --> 12:19.190
So let us rebuild, uh, the image.

12:21.620 --> 12:27.620
And now you can see it's installing all the dependencies during the image building phase, so that when

12:27.620 --> 12:31.070
we create the container, it's able to run the app right away.

12:31.550 --> 12:32.780
Pretty cool.

12:34.670 --> 12:36.230
So once you.

12:36.260 --> 12:43.670
So once because the developer was so, um, helpful in giving us the different ways that this app can

12:43.670 --> 12:44.390
be run.

12:44.390 --> 12:50.780
It helped us make better informed decisions about how we should run the app within our container.

12:50.780 --> 12:56.390
Because now let's imagine I pushed this image onto Docker Hub, and I'm ready to create a container

12:56.390 --> 12:57.230
that runs it.

12:57.230 --> 13:00.950
The container is going to be able to run it right away.

13:00.950 --> 13:03.560
So docker build t dash spring boot demo.

13:03.560 --> 13:06.320
Let's just reuse the command from earlier.

13:08.840 --> 13:10.310
It ran it right away.

13:10.310 --> 13:14.150
It already detected all the dependencies and we were good to go.

13:14.150 --> 13:16.670
So if we go to localhost 8080.

13:17.480 --> 13:19.010
Wonderful.

13:19.220 --> 13:19.880
All right.

13:19.910 --> 13:21.710
Now there's actually a third.

13:22.160 --> 13:22.820
Excuse me.

13:22.820 --> 13:27.320
There's actually a third option, uh, given to us to run the app.

13:27.320 --> 13:30.350
We can use Maven to package the application.

13:30.350 --> 13:35.660
And it's the and its dependencies into a self-contained Jar file.

13:35.690 --> 13:40.730
Then we can run the Jar file using Java jar.

13:41.090 --> 13:42.380
All right.

13:42.380 --> 13:49.970
So here what I can do is say run maven package.

13:49.970 --> 13:53.360
What that's going to do is install the dependencies.

13:53.360 --> 13:54.920
It's going to build the source code.

13:54.920 --> 13:58.760
And it's going to combine everything into a self-contained Jar file.

13:58.760 --> 14:07.790
So after we run Maven package we can just say over here Java dash jar.

14:09.680 --> 14:12.530
And now let's just go ahead and copy over the remaining command.

14:12.530 --> 14:16.730
So all we need is the command to run the code.

14:16.730 --> 14:20.420
And we can set that up inside of our Docker file.

14:20.960 --> 14:22.340
So now.

14:24.380 --> 14:27.170
Um I'm going to rebuild.

14:30.620 --> 14:32.390
I'm going to rebuild our image.

14:35.450 --> 14:39.950
Here you can see Maven package is downloading all the dependencies.

14:39.950 --> 14:45.380
It's going to build our code, and the resulting Jar file is going to package up the source code as

14:45.380 --> 14:52.370
well as the dependencies, which means we can just run it using a simple Java jar command afterwards.

14:56.810 --> 15:00.530
It's taking quite some time to do so.

15:00.770 --> 15:01.310
All right.

15:01.340 --> 15:13.970
Now I'm going to say Dot, let's just reuse the one from before unable to access jar file Demo1 dash

15:13.970 --> 15:15.830
snapshot jar.

15:16.250 --> 15:18.320
There seems to be an issue.

15:18.350 --> 15:20.480
How are we going to troubleshoot this issue?

15:20.510 --> 15:21.620
Worry not.

15:21.650 --> 15:26.150
We have complete transparency over what's happening inside the working directory.

15:26.150 --> 15:29.270
So this is a very useful tool to troubleshoot.

15:29.270 --> 15:30.980
I recommend you get used to it.

15:30.980 --> 15:39.150
Starting up an interactive shell inside of your container to know exactly what's happening in it.

15:40.230 --> 15:40.620
Uh.

15:40.620 --> 15:41.730
Dash it.

15:44.550 --> 15:46.800
Um, you know what?

15:46.800 --> 15:51.600
I can already see what the mistake is, but, um, whatever.

15:51.600 --> 15:52.890
Let's just do RLS.

15:53.040 --> 15:57.750
So here we have Maven Pom.xml source and the target folder.

15:57.750 --> 16:04.290
Exactly what was copied over the jar file is actually present inside of the target folder itself.

16:04.290 --> 16:13.350
So if I do CD target and then RLS target slash demo oh one snapshot jar.

16:13.350 --> 16:19.050
So when when it's at the working directory it didn't see the jar file.

16:19.050 --> 16:20.670
It saw a target folder.

16:20.670 --> 16:24.120
And then inside the target folder is where the jar file is.

16:24.120 --> 16:28.410
So I made a mistake of not reading the full instruction.

16:31.350 --> 16:37.020
Sorry guys, I feel like I'm talking too much, but I just want to make sure that you guys get everything

16:37.020 --> 16:38.070
that's going on.

16:38.070 --> 16:44.880
So now if I rebuild the image so that we give the container the proper command, everything should work

16:44.880 --> 16:45.930
smoothly.

16:48.630 --> 16:50.100
Beautiful.

16:50.160 --> 16:57.060
When you've already got the jar file set up, prepackaging everything the code's already compiled,

16:57.060 --> 16:59.040
you just run Java jar.

16:59.070 --> 17:06.330
The container started very fast, starting up the container running just a simple jar file as opposed

17:06.330 --> 17:10.740
to running Maven spring boot run with the other one.

17:10.740 --> 17:15.000
So Maven Spring Boot Run has to build and actually compile.

17:15.000 --> 17:19.200
Then run the application code based on the dependencies that are provided.

17:19.200 --> 17:26.730
That took a much longer time than just running a jar file where everything was already built and prepackaged.

17:27.000 --> 17:28.350
All right, guys, that's pretty much it.

17:28.350 --> 17:31.350
Now we're going to move on to source code number seven.

17:31.350 --> 17:33.300
I'll see you in the next one.
