-: In this section, we're gonna start
to really get a better idea
of what was really occurring on our terminal
when we executed that Docker build command.
We're going to walk through each of these steps
and not really analyze the structure of each of them
but really analyze the effect that they had
on the image that we were building.
So to get started, I first want to talk a little bit
about the output that we saw
in our terminal when we executed the Docker build command.
So first things first, why do we use Docker build?
Well, this is a new command that we have not used
before tied to the Docker CLI.
Remember what we said a little bit ago?
When we create our Docker file,
we then feed it into the Docker client,
which turns around and gives your file off
to the Docker server
and that's what builds your usable image.
So when we ran Docker build dot,
that was us giving our Docker file off to the Docker CLI.
The build command is what we use to take a Docker file
and generate an image out of it.
The dot right here is specifying
what is called the build context.
The build context is essentially the set of files
and folders that belong to our project.
It's a set of files and folders
that we want to kind of encapsulate
or wrap in this container,
and we'll see some better examples
of exactly what the build context is used for
later on throughout the course,
as our docker builds start to get a little bit more complex.
After running that command, we then very quickly
saw a whole bunch of output start to scroll on by.
The first thing I want you to notice here
is that for every line of configuration
that we put into our Docker file,
we got an additional step added to this flow.
So I see step one of three corresponds
to the first line of our Docker file.
I see step two of three corresponding to the second line
and I bet you can guess the third one down here.
Step three of three corresponded
to the third line of the docker file.
Now, with the very first step where we said from Alpine,
the first thing that occurred was that Docker server
looked at our local build cash and it checked to see
if it has ever downloaded an image called Alpine before.
In our case, it probably hasn't.
So the first thing that occurred
was the Docker server reached out to the Docker hub,
which you'll recall is a repository
of existing Docker images that are free for public use.
And it downloaded that image, the image called Alpine.
So pool complete means, yep, it was successfully downloaded
and well, it really tells you that very clearly right here,
downloaded newer image for Alpine latest.
So that first step right there, kind of boring.
We basically just downloaded an initial
starting image to use as a base.
Things started to get a little bit more interesting
on step number two right here.
So there's a couple of lines of code
or output right here that I want you to really
take a very good look at.
You'll notice the first line right here
says running in and then an ID.
So that's very key right there.
I want you to remember that for just a second.
And then a little bit lower,
you'll notice that it says removing
intermediate container and it printed out
the exact same ID that we saw back up there.
So it looks like this ID right here
is the ID of a container, but what container?
We'll dive into that in just a second
when we look at a diagram to kind of explain this flow.
You'll notice that we also saw some very similar output
down here for step three as well,
where it said running in blah, blah, blah.
And then very shortly after that,
removing intermediate container.
One of the last thing I wanna point out here
is that for step number one up here,
you'll notice that there is no kind
of like intermediate container printout.
So it appears that for every instruction
that we added to the docker file besides the first one,
it appears that some like container of sorts was created.
So that in mind, let's flip over to a diagram
and really walk through what just occurred.
All right.
Now, I know we're going through this stuff
like really intense and in depth,
but honestly, getting a very fundamental
or solid understanding of this docker build process
is really gonna help you understand Docker in general.
That's why we're going through so much detail.
Okay, so in this diagram,
we've got a container on the right hand side.
We've got the alpine image on the bottom left,
and then our series of three commands over here.
So the first thing we did was specify from Alpine.
And as we saw, that basically went out
and downloaded the Alpine image off of Docker hub.
Remember that an image has a file system snapshot
and some startup command.
And at this point, we don't really know
what the startup command for Alpine is,
but we don't really care that much.
The next line was the run APK add update ReDIS.
So here's exactly what happened behind the scenes.
When Docker server saw this line
of configuration right here, it looked back
at the last step that just occurred.
So look back at this step from Alpine step.
It looked at the image that came out of that previous step.
The image that came out of the previous step
was the Alpine image.
Then on the run line right here,
it took that image and created a new container out of it.
So in memory, we very temporarily got a brand new container
created at the very start of step number two.
And that's what this running
in blah, blah, blah right here means.
It means that it created a temporary container
out of the image that was sourced during the previous step.
So we can kind of imagine that we took the entire
file system snapshot from the Alpine image
and we stuffed it into this very temporary container
that was created just for the second step right here,
or the second instruction.
After creating this temporary container,
this command right here,
the command that we just added on was executed
inside that container as its primary running process.
So we took that run command,
we took that line or that full command right there,
and we executed it as a process inside of the container.
So this is this container's primary running process.
As we said in the last video, APK is a package manager
that is built into the Alpine image.
So this command executed inside the container,
and while it executed,
it went through the process of downloading ReDIS.
That's what happened right here.
It downloaded and installed ReDIS
and a couple of dependencies for ReDIS.
So we can imagine that during that installation process,
we maybe got some like new folder
on this container's hard drive right there.
Maybe it was something called like Simply ReDIS.
Now, I want this to represent the ReDIS program.
It didn't install it in the route directory
or anything like that, but let's just imagine
that APK add downloaded and installed ReDIS
onto this container's little hard drive right here.
So we now have a container that has a file system snapshot
that contains the newly installed copy of ReDIS.
Now, look at what happened immediately after that.
After that container, or excuse me,
after that package was installed,
we then stopped that container.
We took a file system snapshot of that container
and then we stopped it entirely.
So we're saying right here that temporary container
that was just created, we stop it,
and we then take its current file system snapshot,
and we save it as a temporary image with this ID right here.
So the output of everything inside of step number two
is a new image that contains just the changes
that we made during this step.
So we can now kind of imagine that this ID right here,
this is the ID to a very temporary image.
So I'm now gonna update the image down here
on the top left hand side,
and I'm gonna say that is the 38EC image.
And inside that image, it now has a installed copy of ReDIS.
And we also threw away that intermediate container.
So that is the end result of step number two.
In total, we created a temporary container
out of the Alpine image.
We executed this command inside that container,
and then we took that container's file system
and saved it as a temporary image.
So we now have this very temporary file system
snapshot right here that has ReDIS included.
Then we move onto step number three,
where we execute CMD right here.
So I bet you can imagine what happens here.
With CMD, we're going to look at the image
that was generated during the previous step.
So in this case, the image that was taken
from the previous step is this 38EC image.
We create a new very temporary container out of it,
and when we make that container,
we take the image's file system snapshot
and stuff it into this container.
And then with the CMD, this is setting the primary command
or the primary process of the container.
So the container does not actually execute ReDIS server.
It doesn't execute this command.
It just tells the container,
"Hey, like just so you know,
if you were to ever run for real,
you should be running ReDIS server as your primary command."
So the container is told this is supposed to be
your intermediate or something.
This is supposed to be your primary command.
And then it shuts down that container and takes a snapshot
of its file system and its primary command.
So the end result is successfully built.
This idea right here,
this is the final image that was created
out of this entire series of steps.
So in step number three, at the very end,
we remove the intermediate container,
we take a snapshot of its file system
and its primary command,
and then we save it as an output,
as an image with an ID of FC60.
So here's the container, the very temporary one.
We take a snapshot of its file system,
so I'm gonna put it over here.
And we also take a snapshot of its running primary command,
or excuse me, not running primary command,
but primary command that should be executed
when the container starts up in the future.
And so we specify the startup command as ReDIS server,
and then we save that entire thing
as an image with the ID of FC60.
And so the end result is this right here.
The end result is our image with that ID
that has our full file system snapshot with ReDIS installed,
and a startup command that has been specified.
All right, so at long last, that is the full story.
That is what happened with a Docker file.
Now, the real takeaway that I want you to understand here
is that basically, along every step along the way,
not basically every step, but really every step
along the way with every additional instruction,
we essentially take the image that was generated
during the previous step.
We create a new container out of it,
we execute a command in the container
or make a change to its file system.
We then look at that container,
we take a snapshot of its file system,
and save it as an output for the next
instruction along the chain.
And then when there is no more instructions to execute,
the image that was generated during that last step
is output from the entire process
as the final image that we really care about.
Whew, so that's a lot of information.
So let's take a quick pause right here,
and we'll continue in the next section.