0: Welcome back to introduction to containers and Docker and at this point,
we're well aware that we wouldn't have been able to complete any of our previous
lessons if not for a few Docker images we've been using
such as the Alpine image and the Nginx image in the hands-on lab,
as well as the hello world image we use to initially demonstrate how to actually
run a Docker container but what is an image? Well, in this lesson,
we're going to talk about, well, exactly that.
We're going to look at what an image is.
We're going to look at how images can be created via something called a
Docker file and then we're going to go ahead and take a look at that hello
world image the Docker file that built it and go through that line by line to
see just how these Docker files can be created and produce the images we use.
So we're not actually going to be on the terminal at all for this lesson.
However,
you will want a browser tab open because we are going to check some things out
in the Docker hub, but for now let's take a step back and again,
consider what an image actually is. Well,
a Docker image is the source of the container. Well,
if you're familiar at all with virtual machines,
it's that same or a similar concept as having a gold image or a
base image that your virtual machine is based upon.
The only difference is containers and Docker have the base image set up in a
way to increase reusability, decrease disk space,
and ensure that when we actually create the image,
the image creation goes quickly and to achieve this,
our Docker images are comprised of layers.
So we'll see what this means quite literally,
when we take a look at our actual Docker file for the hello world container but
essentially when we say an image is comprised of layers,
what we mean is
that the creation of the image is essentially broken down into general steps and
these steps will contain all code. All of the runtime libraries, variables,
configurations, installations, packages,
everything we actually need to build the base image
and have the resulting container based on that image perform the actual job it
needs to perform.
And these layers that we create are then cached which in turn means that when we
deploy any containers, based on this image after the initial build,
the actual creation and launch of that container is going to be much quicker to
deploy and is also going to take up less disk space than if we were trying to
use a standard virtual machine image. Now,
when we create a Docker image,
the intent of the actual image is to contain everything we need to launch your
application or service.
That means when we perform a Docker run on the image we've created,
we actually shouldn't have to do many of the things we did in the previous
section.
While of course there's nothing wrong or inaccurate with spinning up a Docker
server to run commands, to test things out,
to preemptively figure out how you're going to configure an environment,
when you're actually sharing and sending images and production,
that image should contain everything in a production environment where you're
using production containers.
There should be very little need for us to actually go in and intervene with the
container build or change the way the container behaves. Again, ideally,
we're going to set everything up in our Docker file.
That Docker file is going to build an image and in turn,
that image is going to be all we need to deploy our application or our service.
Now, at this point, when it comes to creating Docker images,
you're probably very much wondering how you can create an image from scratch if
it's not based on anything. Well,
as with when creating a virtual machine image,
images are based on other images,
images can have what is called a parent image
and most of the time when we were creating our applications and services,
this is what we can leverage.
We can pull down a parent image from the Docker hub,
generally one that supplied either officially by Docker or the Docker community
or one that supplied by the distro creators themselves.
So there really isn't the need to recreate an image from scratch each time
if you want to run an application on Ubuntu and a base Ubuntu container
already exists and as we saw, we have Alpine,
we can run base Nginx containers that already have web servers set up.
The Docker hub has a countless amount of images that we can base our work
on. Of course,
if we are in a situation in which there is no parent image,
then we can create what is called a base image from scratch.
So let's go ahead and let's take a look at the hello world Docker file
so we can see how a Docker file that's actually made to create an image relates
to these concepts. So in your web browser, go ahead,
go to hub.docker.com/_/hello-world,
or click the link in the description and let's take a look at this actual hello
world image. So again,
here I am at hub.docker.com/_/hello
world.
You can see that this is a Docker official image and provides an example of
minimal Dockerization and what we specifically want to do is we want to scroll
down, we'll go past this description and quick reference,
and we have this link here, simple tags and shared tags.
So under shared tags, we see latest colon and then Linux let's click on that
and this is going to take us to the GitHub repo that stores the Docker file that
builds our image. So let me go ahead and zoom in
a little here specifically to this nice simple Docker file
and as you can,
the Docker file for our hello world image is actually only three
lines long,
and it starts initially with this from scratch line and when Docker file
starts with, from scratch,
then you know that this is creating a base image.
This is not based on a parent image at all and when we create a base
image from scratch,
the second line in the Docker file needs to be the line that
defines the file system layer and in this case,
it's doing this by copying a hello binary that exists in
this directory.
So if I were to zoom out again to make this a little easier drop down to
this hello world folder, we can see we have this hello binary here
and the Docker file is going to use that binary specifically to create the
initial root file system and then finally,
there's one last thing that we have to do in the Docker file,
or rather that Docker does when building an image based on this file and
that's the command line and remember how in our
previous section, we discussed that when we run a Docker container,
it specifically runs a single command and then when that command finishes exits
out the container, well,
this is the command that we're talking about and in this case,
this is set to run that hello binary script that will output the information
we've seen previously on our terminal when we actually launch
the hello world container. Now, as noted,
if the command run during this command line is not persistent,
the container will automatically exit after it's run and that of course is the
behavior we expect here from this hello world container,
but let's take a step back and also take a look at an Nginx container.
So if you have performed the hands-on lab from the previous section, then,
you know,
this is the container we pulled down to set up our web server and obviously this
container image is set up to provide us with a container that runs Nginx.
So again,
I'm going to scroll down past this quick reference and let's select the latest
build of the image and again,
this is going to take us to a Docker file only this time, as we can see,
it's a bit more substantial and we don't need to worry about each
individual step that's going on here. Instead,
I just want to focus on a couple of the differences between this and the Hello
world container. Notably,
you may see the very first line here isn't from scratch.
Instead it defines a parent image,
specifically Debian buster and the slim,
or the most lightweight version of Debian buster that we can use
and you'll notice after this,
we do not have a copy line defining a file system because the root file
system is already defined in this image.
So when we build an image based upon a parent image,
all of the layers and everything that needs to happen to create that parent
image is still going to happen and then afterwards,
it's going to run everything for our actual Nginx image.
So first it will process all the layers,
need it to create a Debian buster slim container and then it will go
ahead and add all of these layers for Nginx.
If we scroll down to the bottom of this,
we can see that we also have the command line supplied at the very end
of the file and this time it's running Nginx
persistently.
So ideally when this container is launched and this command is run the container
isn't going to automatically shut down. Now,
finally, we mentioned early on in this lesson,
that containers are built in layers well,
of all of these files and all of these commands, what is considered a layer?
Well,
let's go back to our hello world image just because it's a little cleaner to
look at, but each line is just a layer.
So from scratch where it defines this as a base image, that's layer one,
then when it creates the root file system and adds the initial hello,
binary and related files, which there's only one file there. That's layer two.
So it's going to go ahead and it's going to catch that and then once it's
finished that it's going to run the final command and then again,
that is layer three. So at this point,
we know that every container is based upon a source image,
unless it happens to be creating a base image itself and we know a base image
is an image based on the scratch templates with the first layer,
defining the file system or the root file system and we also know that a parent
image is the image in which we can base a, another Docker image upon.
So as we note it,
the Nginx image is based on Debian buster and we know that when we build our
images, they are comprised of cached layers and these layers help us increase
reusability, decreased disk base,
and ensure that when we deploy our actual containers,
the deployment happens much faster than if we were to say,
to deploy an entire virtual machine.
So in our next lesson,
we're going to go ahead and get hands on by creating our very own Docker file.
So I will see you there. Thanks for watching.