Docker containers are very popular nowadays. But why
to get a glimpse of their usefulness?
Just think about a database server that we can create with maria DB. The classic way
we install it with a pseudo
app, install maria dash DD server command.
Then we configure its settings by modifying files in the Etsy, mysql directory.
We create a few databases,
we configure database users
assign privileges and so on.
Now let's say we're happy with our setup and we want to
move it to a more powerful computer somewhere in the cloud.
The problem is that all its components are scattered all over the place.
The settings for Maria DB are in one directory.
The databases are in some other directory logs in another one
gathering and migrating all of these things can be a hassle.
But what if our maria DB setup would have been created in a Docker container instead.
Now everything would exist inside this container,
the daemon, the configuration files, the logs and the databases.
All we would need to do is copy this container to some
other computer and everything will work exactly the same as it did before
containers, encapsulate applications. This makes them portable
and easy to move around
as easy as copying and pasting a file from one location to another.
Once we're happy with a containerized application,
we can deploy it to tens of different servers at scale.
The same thing that Kubernetes does.
And part of the reason why it's so popular to understand how to work with Docker.
Let's jump right into some practical examples.
All right. Now, let's dive into our practical exercises.
Let's say we're Docker beginners and we have
no idea what commands we have available.
We can quickly get an overview of how to use the Docker utility with this command
Docker dash dash help.
And we notice the search subcommand
and this can help us find the engine X image we need if we type
clear and we'll type in Docker
search
engine
and we've got a ton of these.
Now, an image provides everything that is needed to create and start a container. In
this case, it includes the engine X daemon,
the software libraries that requires the configuration files, scripts and so on
this first image seems to be the best match. In our case,
many people have added it to their favorites list. So it has a lot of stars.
Furthermore, it's also marked as the official image.
We'll need to download this image
and pull it to our computer.
We can use the name in our results list under the name column.
So the command will use
this Docker Pole and Janette's
in the previous screen. I did see an image from
Ubuntu farther down the list. So we'll download that as well.
Type Docker Pole,
the Boon two Engine X.
Now you'll notice in both of these
where it says Engine X colon. Latest.
The last part latest is called the image tag.
We can think of it as a label for a Tshirt
in the store.
We can buy the same Tshirt in different sizes like small, medium and large.
So the labels on clothes can be SM or L
and it's the same thing for container images.
The engine X image has many different variations.
Now it's still engine X but in many different shapes and sizes.
For example, there are multiple versions for the engine X build
a tag like latest points to the latest versions available and
a tag like 1.24 0.0 would point to the 1.24 0.0 version
by providing the correct tag, we can pick the exact engine X build that we want.
So how do we use this tag in a command?
Well,
let's pull an older version of engine X to see an example
to get version 1.22 0.1 we'll use a command like this.
Now we're saying Dockerpool
engine X colon 1.22 0.1.
Now if we don't specify a tag like we did earlier,
then Docker will assume that we want the latest version
to be more accurate the image that is tagged as latest.
And here we go. Now we've got an image for engine X 1.22 0.1.
At this point, we have some images that we don't really need.
So how do we delete them? Well, first, let's see what images we have.
OK. So as we're looking at this, we don't need this image
and we don't need this one
to delete the Ubuntu engine X image. We can use the RMI or remove image command.
There we go.
Now we'll do Docker images.
When we got two
to delete the last image, we can't just provide its name alone.
That's because both have the same name, Ingen
X and Docker wouldn't know which one we want to remove.
So we'll need to specify the tag as well
and we can delete the old version of Ingen
X with this command
colon
1.22 0.1.
We set that tag
and there we go.
Now let's move on to the next part. How do we actually create and run a container
quite easily
with the Docker, run command followed by the image name.
And the tag is optional.
In our case, we'll type in Docker,
run
int
this command creates the container and also runs the engine X daemon inside it.
But notice the problem. We're now stuck inside this container.
We can see status messages generated in the container,
but we can't type other commands
and this is actually a common problem.
Docker beginners run into before they get used to the workflow.
Let's fix this problem first,
we'll press control C to detach from this container's environment.
And unfortunately, this keyboard combination will also stop the container.
OK? But let's create and run another one
and we'll see how to do it correctly this time for this purpose,
we'll use a few options.
We'll start by typing Docker run,
let me clear my screen here
and then we'll add the command options that we need.
And the first one is dash dash detach which
will make Docker detach us from the container,
so we don't get stuck inside it anymore.
The next one is dash dash publish
8080 colon 80
I'll type this in,
ok.
And this option will make our engine X daemon
running in this container accessible to the outside world.
Now, the option parameter 8080 colon 80 might look a little confusing,
but this tells Docker to redirect network traffic.
So anything that comes to port 8080 on our computer
will be redirected to port 80 inside the container.
So an easy way to think about this is just left to right. We're going from the computer
to the container
and the final option we'll use is dash dash name and pick a name for our container.
Otherwise, Docker will automatically generate names for us like relaxed leader
beg
and this would make it harder to identify which containers which
when we have many of them running on the system.
And then finally, at the end of our command, we'll specify the image we want to use,
which in this case is engine
X.
When we run this Docker will generate a unique identifier for this container.
And that's what we see in the output here.
Now, how can we see what containers are currently running?
Well, let's get some help again.
We'll type Docker help and then we'll scroll up here.
Oh, look, here's the command to list containers. PS,
so let's run Docker PS,
everything seems to look ok here.
But remember the first container we created the one that we
force exited with control C why is that not listed here?
Well,
because Docker PS only lists running containers but not the ones that are stopped.
So how can we list all containers even those that aren't running?
Well, let's get some help with
Docker PS dash dash help.
Ah dash A or dash all
here is the option we're looking for.
So if we run Docker
PS dash dash all.
Ok. Now we've got a few of them in here.
So now we could see our running container and then
a couple of containers that just didn't work out.
The status column shows that one is up, so it's running
and the other ones have a status saying exited. So that's stopped.
Now to start our older container we can use a Docker start command.
This can be followed by either the container name that we see in the last column here
or the container ID
that we see from the first column.
So let's use a container ID,
we'll say Docker start.
All right.
Now if we run Docker ps
ah we can see that both of them are running
now under the ports column. We have one here that says 80 slash TCP.
Let's stop this container that says 80 slash TCP under the ports column.
We didn't publish ports for the first one we created.
So the engine X web server is not easily accessible
and we can use the Docker stop command followed by the name of the container.
And speaking of published ports,
we can actually test if port 8080 is redirected to port 80 on our container.
And for this purpose, we'll use the Netcat command.
We type in NC localhost 8080
and this connects us to port 8080 on our local machine.
And Docker should now redirect us to port 80 on the container.
So we're practically connected to the engine X running in there. And if we type in get
front slash,
we can send the get command to the web server
which should return the index page in text format.
In this case, it does
this output confirms that our containerized engine X works
and the port is indeed published to our host.
We'll press control D to exit the NETCAT session.
Now, let's make a note here when we first learn Docker,
it can be a bit confusing about what's the difference
between a Docker run command and a Docker start command.
Both seem to simply start containers
but Docker run is effectively building a container from
an image and configuring it in a certain way.
And only afterwards it starts it
Docker start doesn't build anything.
It just starts a container that was previously
created by the initial Docker run command.
To remember this difference. Think about it this way
if the container does not exist, I need the Docker run command to initialize one.
If the container exists, I need the Docker start command.
Let's continue with our lesson.
Now, how do we remove containers
once again, let's list all of our containers. Even the ones that are stopped
with Docker PS dash dash all
to remove the stopped container. The one with the exited status.
We can use the Docker RM command.
Let's remove
determined Pearlman
and we can do Docker RM.
Lucid
Feynman.
An RM is short for remove
and it's not to be confused with our previous Docker
RM I command which removes images instead of containers.
But speaking of images,
let's explore an EdgeCase we might encounter in the real
world say we want to remove the engine X image.
Now, if we type in Docker
RM I
in
X,
we'll notice an error.
We can't remove this image because a container is still using it.
We first have to remove the container or the containers depending on it. In
this case,
we should remove the container called my web server that we created earlier.
So we'll say Docker RM
my web server
and we get another error,
we can't remove containers that are still running.
So now we have the full picture to remove the image,
we have to go through all of these steps.
First stop the container that depends on the engine X image. So we'll say Docker
stop
my web server.
OK. Now it's stopped. Now let's remove the container.
Docker RM,
my web server
and finally remove the engine X image.
Docker
RM I
it's going to have an eye this time
in
JTE.
All right.
So we type in Docker images
and we have nothing. So we can confirm that that image has been removed.
Now, let's explore another interesting thing about Docker.
In our lesson, we first pulled the image we needed
afterwards, we ran a container based on that image
but Docker can automatically figure things out.
For example, if we type in this command,
Docker will automatically pull in the required image to start this container.
There's no need for us to manually pull the image beforehand.
Now let's jump to a different topic.
Can you spot the problem with our engine X container?
If we want it to work as a web server, we need to make sure it's always available
in the current scenario, if the container experiences an error,
it will enter a stop state
and even worse.
If we reboot our server,
we'll have to log in and manually start our container every time.
Isn't there a way to tell Docker to always keep this running?
Well, there is, let's find it.
So we'll type in man Docker run.
Now, this is a big manual for doc
run command.
So let's type in front slash
to begin a search and then type in restart
policy.
And we're gonna look for this text
and we find this interesting command option
always.
So to create an engine X container that will always restart when it
experiences problems and will also start every time the system boots up,
we can adapt our previous command.
Lets press Q to quit the manual
and we'll return to our Docker run command.
OK? Now we can insert the additional command option. We need
restart always.
And there we go. Since we didn't have engine X colon latest
locally downloaded. Notice that it automatically goes out and downloads it
up to this point.
We worked with publicly available container, images built by other people.
But in the real world, these generic images won't be enough.
We'll either have to modify them to adjust to our
specific needs or we'll need to build our own images.
Let's see how we can do that.
Now, images can be built from zero
but to make life easier, we'll use the engine X image and build on top of it.
The first thing we need to do is create a directory
for our little project and let's call it my image.
OK. Then we'll cd into the directory
here. We can add all the files that we want to add to our final image.
Only one file is needed for our purposes. Now, let's create it with Vim
index dot HTML
and we'll add a simple line of text to it.
OK? It's not valid HTML, but it suits for demo purposes.
Let's save index dot HTML and continue.
Since we have all the files, we need.
The next step is to tell Docker how we want to build this image.
And the instructions should be included with a file with a very specific name,
Docker file with a capital D.
So let's create that with Vim Docker file
and we're going to add in the following text.
Now, the first line instructs Docker to use engine X as the base image.
So that will be the starting point.
And on top of the engine X image, we'll add our desired changes.
The next line tells Docker to copy one file from one location to another.
Specifically index dot HTML. From our current myimage directory
will be copied to user sharex
H TM L index HTML inside the container.
This will replace the preexisting file in that container
with a custom one that we just created.
So we'll see the effect of this later on
and we can save our Docker file at this point.
So we type escape colon WQ.
Now obviously, this is a very simplistic file with very simple instructions.
Other popular instructions are
run
to tell Docker what commands to run to prepare this image.
For example,
we can instruct Docker to install a few additional utilities to the image.
Other important instructions are
C MD
entry point.
This tells Docker what command to run inside this container when it starts up
along with the command parameters that might be required.
Now, the difference between them is that the startup command under C MD is optional.
It can be ignored under certain circumstances.
For example,
if the user provides an alternate way to start the container in a Docker run command,
but the command provided an entry point is not optional.
It will be executed when initializing the container.
Now let's go back to our home directory.
We'll type CD with nothing else.
And let's see how we can build our image.
The usual command is Docker build dash dash tag,
followed by the repository image name tag.
And finally the path to the directory that contains our Docker file.
So in this case, we'll use this command
doctor bill,
dash dash tag.
And we're gonna call this Jeremy
slash
custom engine X
one point. Oh
my image.
Now, Jeremy is the repository name.
If we'd want to publish this on Docker hub and our username. There would be Jeremy.
All of our projects would be stored under this repository called Jeremy.
We can think of it as our own personal folder on Dockerhub
custom engine X is the name that we choose for our image
and 1.0 is the tag for our 1.0 version of this image.
Finally,
my image is a directory where we included our project files and our Docker file.
Now you can always use man
Docker build
and scroll to the examples section.
If you need a quick refresh on how to use this command.
It's worth mentioning that the repository name can be omitted if we don't need it.
We can also run a man such as this.
We can also run Docker build dash dash tag, custom engine, X colon 1.0
my image.
Now let's move on to our next lesson.