Transcript for:
Introduction to Docker for Beginners

Hello and welcome to the Docker for beginners  course. My name is moonshot 100, and I will be   your instructor for this course. I'm a DevOps  and cloud trainer at code cloud comm, which is   an interactive hands on online learning platform.  I've been working in the industry as a consultant   for over 13 years and have helped hundreds of  1000s of students learn technology in a fun and   interactive way. In this course, you will learn  Docker through a series of lectures that use   animation illustration, and some fun analogies  that simplify complex concepts with demos that   will show you how to install and get started with  Docker. And most importantly, we have hands on   labs that you can access right in your browser.  I will explain more about it in a bit. But first,   let's look at the objectives of this course.  In this course, we first try to understand what   containers are, what Docker is, and why you might  need it and what it can do for you. We will see   how to run a Docker container how to build your  own Docker image, we will see networking in Docker   and how to use Docker compose what Docker registry  is how to deploy your own private registry. And we   then look at some of these concepts in depth. And  we try to understand how Docker really works under   the hood. We look at Docker for Windows and Mac  before finally getting a basic introduction to   container orchestration tools like Docker, swarm,  and Kubernetes. Here's a quick note about hands on   labs. First of all, to complete this course, you  don't have to set up your own labs. Well, you may   set it up if you wish to, if you wish to have your  own environment, and we have a demo as well. But   as part of this course, we provide real labs that  you can access right in your browser anywhere,   anytime and as many times as you want. The labs  give you instant access to a terminal to a Docker   host and an accompanying quiz portal. The quiz  portal asks a set of questions such as exploring   the environment and gathering information. Or you  might be asked to perform an action such as run   Docker container. The quiz portal then validates  your work and gives you feedback instantly. every   lecture in this course is accompanied by  such challenging interactive quizzes that   makes learning Docker a fun activity. So I hope  you're as thrilled as I am to get started. So let   us begin. We're going to start by looking at  a high level overview on why you need Docker,   and what it can do for you. Let me start by  sharing how I got introduced to Docker. And one   of my previous projects, I had this requirement  to set up an end to end application stack,   including various different technologies, like  a web server using node j s, and a database such   as MongoDB, and a messaging system like Redis,  and an orchestration tool like Ansible, we had   a lot of issues developing this application stack  with all these different components. First of all,   their compatibility with the underlying OS was an  issue, we had to ensure that all these different   services were compatible with the version of OS  we were planning to use. There have been times   when certain version of the services were not  compatible with the OS. And we've had to go back   and look at different OS that was compatible with  all of these different services. Secondly, we had   to check the compatibility between the services  and the libraries and dependencies on the OS.   We've had issues where one service requires one  version of a dependent library, whereas another   service requires another version, the architecture  of our application changed over time, we've had to   upgrade to newer versions of these components, or  change the database, etc. And every time something   changed, we had to go through the same process  of checking compatibility between these various   components, and the underlying infrastructure.  This compatibility matrix issue is usually   referred to ask the matrix from hell. Next, every  time we had a new developer on board, we found it   really difficult to set up a new environment,  the new developers had to follow a large set   of instructions and run hundreds of commands to  finally set up their environments, we had to make   sure they were using the right operating system,  the right versions of each of these components.   And each developer had to set all that up  by himself each time. He also had different   development tests and production environments. One  developer may be comfortable using one or less and   the others may be comfortable using another one.  And so we couldn't guarantee that the application   that we were building would run the same way in  different environments. And so all of this made   our life in developing better Building and  shipping the application really difficult.   So I needed something that could help us with the  compatibility issue. And something that will allow   us to modify or change these components without  affecting the other components and even modify the   underlying operating systems as required. And  that search landed me on Docker. with Docker,   I was able to run each component in a  separate container with its own dependencies,   and its own libraries, all on the same VM  and the OS, but within separate environments,   or containers. We just had to build the Docker  configuration once and all our developers could   now get started with a simple Docker run command.  irrespective of what the underlying operating   system they're on. All they needed to do was  to make sure they had Docker installed on their   systems. So what are containers, containers  are completely isolated environments. As in   they can have their own processes or services,  their own network interfaces, their own mounts,   just like washing machines, except they all share  the same OS kernel. We will look at what that   means in a bit. But it's also important to note  that containers are not new with Docker containers   have existed for about 10 years now and some of  the different types of containers are Aleksey LSD   like CFS, etc. Docker utilizes Aleksey containers.  Setting up these container environments is hard as   they are very low level and that is where Docker  offers a high level two, with several powerful   functionalities making it really easy for end  users like us. To understand how Docker works,   let us revisit some basic concepts of operating  systems First, if you look at operating systems   like Ubuntu, Fedora, Susi or CentOS, they all  consist of two things, an OS kernel and a set   of software. The OS kernel is responsible for  interacting with the underlying hardware, while   the OS kernel remains the same, which is Linux. In  this case, it's the software above it that makes   these operating systems different. This software  may consist of a different user interface drivers,   compilers, file managers, developer tools, etc. So  you have a common Linux kernel shared across all   OSS and some custom software that differentiate  operating systems from each other. We said earlier   that Docker containers share the underlying  kernel. So what does that actually mean? Sharing   the kernel? Let's say we have a system with an  Ubuntu OS with Docker installed on it. Docker   can run any flavor of OS on top of it, as long  as they're all based on the same kernel. In this   case, Linux. If the underlying OS is Ubuntu,  Docker can run a container based on another   distribution like Debian Fedora Susi or CentOS  each Docker container only has the additional   software that we just talked about in the  previous slide that makes these operating systems   different. And Docker utilizes the underlying  kernel of the Docker host, which works with all   OSS above. So what is an OS that do not share the  same kernel as this windows. And so you won't be   able to run a Windows based container on a Docker  host with Linux on it. For that you will require   Docker on a Windows Server. Now it is when I say  this, that most of my students go, Hey, hold on   there. That's not true. And they install Docker  on Windows, run a container based on Linux and go   see it's possible. Well, when you install Docker  on Windows and run a Linux container on Windows,   you're not really running a Linux container on  Windows, Windows runs a Linux container on a Linux   virtual machine under the hoods. So it's really  a Linux container on Linux virtual machine on   Windows. We discuss more about this on the Docker  on Windows or Mac later during this course. Now,   you might ask, isn't that a disadvantage then not  being able to run another kernel? On the OS? The   answer is no. Because unlike hypervisors,  Docker is not meant to virtualize and run   different operating systems and kernels on the  same hardware. The main purpose of Docker is   to package and containerize applications and  to ship them and to run them anywhere anytime,   as many times as you want. So that brings us  to the differences between virtual machines   and containers, something that we tend to do  especially those from a virtualization background.   As you can see on the right, in case of Docker,  we have the underlying hardware, infrastructure   and then the OS and then Docker installed on  the OS. Docker then manages the containers that   run with libraries and dependencies alone.  In case of virtual machines, we have the   hypervisor like ESX on the hardware, and then  the virtual machines on them. As you can see,   each virtual machine has its own oil inside it.  Then the dependencies and then the application.   The overhead causes higher utilization of  underlying resources as there are multiple   virtual operating systems and kernels running. The  virtual machines also consumed higher disk space,   as each VM is heavy, and is usually in gigabytes  in size, whereas Docker containers are lightweight   and are usually in megabytes in size. This allows  Docker containers to boot up faster, usually in a   matter of seconds, whereas VMs as we know, takes  minutes to boot up as it needs to boot up the   entire operating system. It's also important  to note that Docker has less isolation as   more resources are shared between the containers  like kernel, whereas VMs have complete isolation   from each other. Since VMs, don't rely on the  underlying OS or kernel, you can run different   types of applications built on different services  such as Linux based or Windows based apps on the   same hypervisor. So those are some differences  between the two. Now, having said that, it's not   an either container or virtual machine situation.  Its containers and virtual machines. Now, when you   have large environments with 1000s of application  containers running on 1000s of Docker hosts,   you will often see containers provisioned on  virtual Docker hosts. That way, we can utilize the   advantages of both technologies, we can use the  benefits of virtualization, to easily provision   or decommission Docker hosts, as required, at the  same time make use of the benefits of Docker to   easily provision applications and quickly scale  them as required. But remember that in this case,   we will not be provisioning that many virtual  machines as we used to before, because earlier,   we provisioned a virtual machine for each  application. Now, you might provision a virtual   machine for hundreds or 1000s of containers. So  how is it done? There are lots of containerized   versions of applications readily available as of  today. So most organizations have their products   containerized and available in a public Docker  repository called Docker Hub, or Docker store.   For example, you can find images of most common  operating systems, databases, and other services   and tools. Once you identify the images you need,  and you install Docker on your host. Bringing up   an application is as easy as running a Docker run  command with the name of the image. In this case,   running a Docker run Ansible command will run an  instance of Ansible on the Docker host. Similarly   run an instance of MongoDB Redis and node j s  using the Docker run command. If we need to run   multiple instances of the web service, simply  add as many instances as you need and configure   a load balancer of some kind in the front.  In case one of the instances were to fail,   simply destroy that instance and launch anyone.  There are other solutions available for handling   such cases that we will look at later during  this course. And for now, don't focus too much   on the commands. We'll get to that in a bit.  We've been talking about images and containers,   let's understand the difference between the  two. An image is a package or a template,   just like a VM template that you might have worked  within the virtualization world, it is used to   create one or more containers. Containers are  running instances of images that are isolated and   have their own environments and set of processes.  As we have seen before, a lot of products have   been dockerized already, in case you cannot find  what you're looking for. You could create your own   image and push it to Docker Hub repository, making  it available for public. So if you look at it,   traditionally, developers developed applications,  then they hand it over to ops team to deploy and   manage it in production environments. They do  that by providing a set of instructions such   as information about how the host must be set up,  what prerequisites are to be installed on the host   and how the dependencies are to be configured  etc. Since the ops team did not really develop   the application on their own, they struggle  with setting it up. When they hit an issue,   they work with the developers to resolve it.  with Docker, developers and operations teams work   hand in hand to transform the guide into a Docker  file with both of their requirements. This Docker   file is then used to create an image for their  applications. This image can now run on any host   with Docker installed on it, and is guaranteed  to run the same way everywhere. So the ops   team can now simply use the image to deploy the  application. Since the image was already working,   when the developer built it, and operations are  have not modified it. It continues to work the   same way when deployed in production. And that's  one example of how a tool like Docker contributes   to the DevOps culture. Well, that's it for now.  In the upcoming lecture, we will look at how to   get started with Docker. We'll now see how to get  started with Docker. Now Docker has two editions,   the Community Edition and the Enterprise Edition.  The Community Edition is the set of free Docker   products. The Enterprise Edition is the certified  and supported container platform that comes with   enterprise add ons like the image management image  security, universal control plane for managing   and orchestrating container runtimes. But of  course, these come with a price. We will discuss   more about container orchestration later in this  course, and along with some alternatives. For now,   we will go ahead with the Community Edition.  The Community Edition is available on Linux,   Mac, Windows, or on cloud platforms like AWS, or  Azure. In the upcoming demo, we will take a look   at how to install and get started with Docker on  a Linux system. Now, if you are on Mac or Windows,   you have two options, either install a Linux VM  using VirtualBox or some kind of virtualization   platform. And then follow along with the upcoming  demo, which is really the most easiest way to get   started with Docker. The second option is  to install Docker desktop for Mac or adopt   Docker desktop for Windows, which are native  applications. So if that is really what you   want the check out the Docker for Mac and the  windows sections towards the end of this course,   and then head back here. Once you're all  set up. We will now head over to our demo,   and we will take a look at how to install Docker  on a Linux machine. In this demo, we look at how   to install and get started with Docker. First  of all, identify a system physical or virtual   machine or laptop that has a supported operating  system. In my case, I have an Ubuntu VM. Go to   Doc's dot Docker comm and click on Get Docker.  You will be taken to the Docker engine Community   Edition page. That is the free version that we're  after. From the left hand menu, select your system   type. I choose Linux In my case, and then select  your OS flavor. I choose Ubuntu read through the   prerequisites and requirements. Your Ubuntu system  must be 64 bit and one of the supported versions   like this called cosmic bionic or sannio. In my  case, I have a bionic version to confirm view the   Etsy release file. Next uninstaller any older  version if one exists, so let's just make sure   that there's none on my host. So I'll just copy  and paste that command. And I confirm that there   are no older version that exists on my system. The  next step is to set up a repository and install   the software. Now there are two ways to go about  this. The first is using the package manager by   first updating the repository using the apt get  update command, then installing the prerequisite   packages, and then adding Dockers official GPG  keys and then installing Docker. But I'm not   going to go that route. There is an easier way.  If you scroll all the way to the bottom you will   find the instructions to install Docker using the  convenience script. It's a script that automates   the entire installation process and works on  most operating systems. Run the first command   to download a copy of the script and then run the  second command to execute the script to install   Docker automatically. Give it a few minutes to  complete the installation. The installation is   now successful. Let us now check the version  of Docker using the Docker version command. We   have installed version 19.0 3.1. We will now run  a simple container to ensure everything is working   as expected. For this, head over to Docker Hub at  hub Docker Comm. Here you will find a list of the   most popular Docker images like nginx MongoDB,  Alpine, no jazz Redis, etc. Let's search for a   fun image called we'll say we'll say is Dockers  version of kousei which is basically A simple   application that trains a cow saying something. In  this case, it happens to be a well copy the Docker   run command given here. Remember to add sudo  and we will change the message to hello world.   On running this command, Docker pulls the image  of the willsey application from Docker Hub and   runs it. And we have our avail, saying, hello.  Great. We're all set. Remember, for the purpose   of this course, you don't really need to set up  a Docker system on your own. We provide hands   on labs that you will get access to but if you  wish to experiment on your own and follow along,   feel free to do so. We now look at some of the  Docker commands. At the end of this lecture,   you will go through a hands on quiz where you will  practice working with these commands. Let's start   by looking at Docker run command. The Docker run  command is used to run a container from an image   running the Docker run nginx command will run an  instance of the nginx application from the Docker   host if it already exists. If the image is not  present on the host, he will go out to Docker Hub   and pull the image down. But this is only done  the first time. For the subsequent executions,   the same image will be reduced. The docker  ps command lists all running containers and   some basic information about them. Such as  the container ID, the name of the image we   use to run the containers, the current status  and the name of the container. Each container   automatically gets a random ID and Name created  for it by Docker, which in this case is silly   summit. To see all containers running or not  use the dash eight option. This output all   running as well as previously stopped or exited  containers. We'll talk about the command and   port fields shown in this output later in this  course. For now let's just focus on the basic   commands. To stop a running container use the  Docker stop command, but you must provide either   the container ID or the container name in the  stop command. If you're not sure of the name,   run the docker ps command to get it on success.  You will see the name printed out and running   docker ps again will show no running containers.  Running docker ps dash a, however shows the   container silly summit and that it is now an exit  state a few seconds ago. Now what if we don't   want this container lying around consuming space?  What if we want to get rid of it for good? Use the   Docker rm command to remove a stopped or exited  container permanently. If it prints the name back,   we're good. Run the docker ps command again to  verify that it's no longer present. Good. But   what about the nginx image that was downloaded? At  first? We're not using that anymore. So how do we   get rid of that image? But first, how do we see a  list of images present on our host run the Docker   images command to see a list of available images  and their sizes. On our host we have four images   nginx Redis, Ubuntu and Alpine. We will talk about  tags later in this course when we discuss about   images. To remove an image that you no longer  plan to use. Run the Docker Rmi command. Remember,   you must ensure that no containers are running  off of that image before attempting to remove   the image. You must stop and delete all dependent  containers to be able to delete an image. When we   ran the Docker run command earlier, it downloaded  the Ubuntu image as it couldn't find one locally.   What if we simply want to download the image and  keep so when we run the run Docker run command,   we don't want to wait for it to download. Use the  Docker pull command to only pull the image and   not run the container. So in this case, the  Docker pull Ubuntu command pulls the Ubuntu   image and stores it on our host. Let's look at  another example. Say you were to run a Docker   container from an Ubuntu image. When you run the  Docker run Ubuntu command it runs an instance of   Ubuntu image and exits immediately. If you were to  list the running containers, you wouldn't see the   container running. If you list all containers,  including those that are stopped, you will see   that the new container you ran is in an exit  state. Now why is that? Unlike virtual machine   containers are not meant to host an operating  system. Containers are meant to run a specific   task or process such as to host an instance of a  web server or application server or a database,   or simply to carry some kind of computation  or analysis task. Once the task is complete,   the container exits a container only lives as  long as the process inside it is alive. If the   web service inside the container is stopped, or  crash, then the container exits. This is why when   you run a container from an Ubuntu image, it  stops immediately. Because Ubuntu is just an   image of an operating system that is used as the  base image. For other applications. There is no   process or application running in it by default.  If the image isn't running any service, as is   the case with Ubuntu, you could instruct Docker  to run a process with the Docker run command.   For example, a sleep command with a duration  of five seconds. When the container starts,   it runs the sleep command and goes into sleep for  five seconds post with the sleep command exit,   and the container stops. What we just saw was  executing a command when we run the container,   but what if we would like to execute a command  on a running container. For example, when I run   the docker ps command, I can see that there is  a running container which uses the Ubuntu image   and sleeps 400 seconds. Let's say I would like to  see the contents of a file inside this particular   container. I could use the Docker exec command to  execute a command on my Docker container, in this   case to print the contents of the Etsy hosts file.  Finally, let's look at one more option before we   head over to the practice exercises. I'm now going  to run a Docker image I developed for a simple web   application. The repository name is cloud slash  simple web app. It runs a simple web server that   listens on port 8080. When you run a Docker run  command like this, it runs in the foreground or   in an attached mode, meaning you will be attached  to the console or the standard out of the Docker   container. And you will see the output of the  web service on your screen. You won't be able   to do anything else on this console other than  view the output until this Docker container   stops. It won't respond to your inputs. press the  ctrl plus c combination to stop the container and   the application hosted on the container exits and  you get back to your prompt. Another option is to   run the Docker container in the detached mode  by providing the dash D option. This will run   the Docker container in the background mode, and  you will be back to your prompt immediately. The   container will continue to run in the backend,  run the docker ps command to view the running   container. Now if you would like to attach back to  the running container later, run the Docker attach   command and specify the name or ID of the Docker  container. Now remember, if you're specifying the   ID of a container in any Docker command, you can  simply provide the first few characters alone,   just so it is different from the other container  IDs on the host. In this case, I specify a 043 D.   Now don't worry about accessing the UI of the web  server for now. We will look more into that in the   upcoming lectures. For now let's just understand  the basic commands will now get our hands dirty   with the Docker COI. So let's take a look at how  to access the practice lab environments. Next.   Let me now walk you through the hands on lab  practice environment. The links to access the labs   associated with this course are available at code  cloud at code cloud.com slash p slash Docker dash   labs. This link is also given in the description  of this video. Once you're on this page, use the   links given there to access the labs associated  to your lecture. Each lecture has its own lab. So   remember to choose the right lab for your lecture.  The labs open up right in your browser, I would   recommend to use Google Chrome while working with  the labs. The interface consists of two parts,   a terminal on the left and a quiz portal on the  right. The quiz portal on the right gives you   challenges to solve. Follow the quiz and try and  answer the questions asked and complete the tasks   given to you. Each scenario consists of anywhere  from 10 to 20 questions that need to be answered.   Within 30 minutes to an hour. At the top, you have  the question numbers below that is the remaining   time for your lab below that is the question.  If you are not able to solve the challenge,   look for hints in the head section, you may skip  a question by hitting the skip button in the top   right corner. But remember that you will not be  able to go back to a previous question once you   have skipped. If the quiz portal gets stuck for  some reason, click on the quiz portal tab at the   top to open the quiz portal in a separate window.  The terminal gives you access to a real system   running Docker, you can run any Docker command  here and run your own containers or applications.   You will typically be running commands to solve  the task assigned in the quiz portal. You may play   around and experiment with this environment. But  make sure you do that after you've gone through   the quiz so that your work does not interfere with  the tasks provided by the quiz. So let me walk you   through a few questions. There are two types of  questions. Each lab scenario starts with a set of   exploratory multiple choice questions where you're  asked to explore and find information in the given   environment and select the right answer. This is  to get you familiarized with the setup. You're   then asked to perform tasks like run a container,  stop them, delete them, build your own image,   etc. Here, the first question asks us to find  the version of Docker server engine running on   the host. Run the Docker version command in  the terminal and identify the right version.   Then select the appropriate option from the given  choices. Another example is the fourth question   where it asks you to run a container using the  Redis image. If you're not sure of the command,   click on hence and it will show you a hint. We  now run a Redis container using the Docker run   Redis command, wait for the container to run. Once  done, click on Check to check your work. You have   now successfully completed the task. Similarly,  follow along and complete all tasks. Once the   lab exercise is completed. Remember to leave a  feedback and let us know how it went. A few things   to note. These are publicly accessible labs that  anyone can access. So if you catch yourself logged   out during a peak hour, please wait for some time  and try again. Also remember to not store any   private or confidential data on these systems.  Remember that this environment is for learning   purposes only and is only alive for an hour, after  which the lab is destroyed. So does all your work.   But you may start over and access these labs as  many times as you want. until you feel confident.   I will also post solutions to these lab quizzes.  So if you run into issues, you may refer to   those. That's it for now, head over to the first  challenge. And I will see you on the other side.   We will now look at some of the other Docker run  commands. At the end of this lecture, you will go   through a hands on quiz where you will practice  working with these commands. We learned that we   could use the Docker run Redis command to run a  container running a Redis service, in this case,   the latest version of Redis, which happens to be  5.0 dot five as of today. But what if we want to   run another version of Redis like for example,  an older version, say 4.0. Then you specify the   version separated by a colon. This is called a  tag. In that case, Docker pulls an image of the   photo zero version of Redis and runs that. Also,  notice that if you don't specify any tag as in the   first command, Docker will consider the default  tag to be latest. Latest is a tag associated   to the latest version of that software, which  is governed by the authors of their software.   So as a user, how do you find information about  these versions and what is the latest? At Docker   hub.com look up an image and you will find all the  support tags in its description. Each version of   the software can have multiple short and long tags  associated with it, as seen here. In this case,   the version 5.0 dot five also has the latest tag  on it. Let's now look at inputs. I have a simple   prompt application that when run asked for my name  and on entering my name prints a welcome message   if If I were to Docker eyes this application  and run it as a Docker container like this,   it wouldn't wait for the prompt. It just prints  whatever the application is supposed to bring on   standard out. That is because by default, the  Docker container does not listen to a standard   input. Even though you're attached to its console,  it is not able to read any input from you. It   doesn't have a terminal to read inputs from it  runs in a non interactive mode. If you'd like   to provide your input, you must map the standard  input of your host to the Docker container using   the dash I parameter. The dash I parameter is  for interactive mode. And when I input my name,   it prints the expected output. But there is  something still missing from this, the prompt   when we run the app, at first, it asked us for our  name. But when dockerized that prompt is missing,   even though it seems to have accepted my input.  That is because the application prompt on the   terminal and we have not attest to the containers  terminal. For this use the dash t option as well.   The dash T stands for a pseudo terminal. So with  the combination of dash IMT. We're now attached   to the terminal, as well as in an interactive mode  on the container. We will now look at Port mapping   or port publishing on containers. Let's go back to  the example where we run a simple web application   in a Docker container on my Docker host. Remember  the underlying host where Docker is installed is   called Docker host or Docker engine. When we run  a containerized web application it runs and we're   able to see that the server is running. But how  does the user access my application. As you can   see, my application is listening on port 5000. So  I could access my application by using Port 5000.   But what IP do I use to access it from a web  browser. There are two options available. One   is to use the IP of the Docker container. Every  Docker container gets an IP assigned by default,   in this case it is 172 dot 17 dot 0.2. Remember  that this is an internal IP and is only accessible   within the Docker host. So if you open a browser  from within the Docker host, you can go to HTTP,   colon forward slash forward slash 172 dot 17 dot  0.1 colon 5000 to access the IP address. But since   this is an internal IP users outside of the Docker  host cannot access it using this IP. For this,   we could use the IP of the Docker host, which  is 190 2.1 68 dot five. But for that to work,   you must have mapped the port inside the Docker  container to a free port on the Docker host.   For example, if I want the users to access my  application through Port 80, on my Docker host,   I could map Port 80 of local host to Port 5000 on  the Docker container using the dash p parameter   in my run command like this. And so the user can  access my application by going to the URL HTTP,   colon slash slash 190 2.1 68 dot 1.5 colon 80. And  all traffic on port 80 on my Docker host, will get   routed to Port 5000 inside the Docker container.  This way you can run multiple instances of your   application and map them to different ports on  the Docker host or run instances of different   applications on different ports. For example, in  this case, I'm running an instance of MySQL that   runs a database on my host and listens on the  default MySQL port, which happens to be 3306,   or another instance of MySQL on another port 8306.  So you can run as many applications like this,   and map them to as many ports as you want. And  of course, you cannot map to the same port on the   Docker host more than once. We will discuss more  about port mapping and networking of containers   in the network lecture later on. Let's now look  at how data is persisted in a Docker container.   For example, let's say you were to run a MySQL  container. When databases and tables are created,   the data files are stored in location slash four  lib MySQL inside the Docker container. Remember,   the Docker container has its own isolated file  system and any changes to any files happen within   the kernel. tainer let's assume you dump a lot  of data into the database. What happens if you   were to delete the MySQL container and remove  it. As soon as you do that, the container along   with all the data inside it gets blown away,  meaning all your data is gone. If you would   like to persist data, you would want to map a  directory outside the container on the Docker   host to a directory inside the container. In this  case, I create a directory called slash OBT slash   data dir and map that to var lib MySQL inside  the Docker container using the dash v option,   and specifying the directory on the Docker host,  followed by a colon and the directory inside the   Docker container. This way when Docker container  runs, it will implicitly mount the external   directory to a folder inside the Docker container.  This way all your data will now be stored in the   external volume at slash RPT slash data directory.  And this will remain even if you delete the Docker   container. The docker ps command is good enough  to get basic details about containers like   their names and IDs. But if you'd like to see  additional details about a specific container,   use the Docker inspect command and provide the  container name or ID. It returns all details   of a container in a JSON format, such as the state  mounts, configuration data, network settings, etc.   Remember to use it when you're required to find  details on a container. And finally, how do we see   the logs of a container we run in the background.  For example, I ran my simple web application using   the dash D parameter and it ran the container  in a detached mode. How do I view the logs   which happens to be the contents written to the  standard out of that container. Use the Docker   logs command and specify the container ID or  name like this. Well, that's it for this lecture,   how to work with the challenges and practice  working with Docker commands. Let's start with   a simple web application written in Python. This  piece of code is used to create a web application   that displays a web page with a background color.  If you look closely into the application code,   you will see a line that sets the background  color to red. Now, that works just fine. However,   if you decide to change the color in the future,  you will have to change the application code. It   is a best practice to move such information out of  the application code and into say an environment   variable called app color. The next time you run  the application set an environment variable called   add color to a desired value. And the application  now has a new color. Once your application gets   packaged into a Docker image, you will then  run it with the Docker run command followed   by the name of the image. However, if you wish to  pass the environment variable as he did before,   he would now use the Docker run commands dash  e option to set an environment variable within   the container. To deploy multiple containers with  different colors. He would run the Docker command   multiple times and set a different value for the  environment variable each time. So how do you find   the environment variable set on a container that's  already running? Use the Docker inspect command to   inspect the properties of a running container.  Under the config section, you will find the list   of Environment Variables set on the container.  Well that's it for this lecture on configuring   environment variables in Docker. Hello, and  welcome to this lecture on Docker images. In this   lecture, we're going to see how to create your  own image. Now before that, why would you need to   create your own image? It could either be because  you cannot find a component or a service that you   want to use as part of your application on Docker  Hub already, or you and your team decided that the   application you're developing will be dockerized  for ease of shipping and deployment. In this case,   I'm going to containerize an application a simple  web application that I have built using the Python   flask framework. First we need to understand  what we are containerizing or what application   we are creating an image for How the application  is built. So start by thinking what you might do.   If you want to deploy the application manually,  we write down the steps required in the right   order. I'm creating an image for a simple web  application. If I were to set it up manually,   I would start with an operating system like  Ubuntu, then update the source repositories using   the abt command, then install dependencies using  the abt command, then install Python dependencies   using the PIP command, then copy over the source  code of my application to a location like RPT   and then finally, run the web server using the  floss command. Now that I have the instructions,   create a Docker file using this. Here's a  quick overview of the process of creating   your own image. First, create a Docker file named  Docker file and write down the instructions for   setting up your application in it, such as  installing dependencies, where to copy the   source code from and to and what the entry  point of the application is, etc. Once done,   build your image using the Docker build command  and specify the Docker file as input as well   as a tag name for the image. This will create an  image locally on your system. To make it available   on the public Docker Hub registry, run the Docker  push command and specify the name of the image you   just created. In this case, the name of the image  is my account name which is mm shot, followed by   the image name, which is my custom app. Now  let's take a closer look at that Docker file.   Docker file is a text file written in a specific  format that Docker can understand. It's in an   instruction and arguments format. For example,  in this Docker file, everything on the left in   caps is an instruction. In this case from run,  copy and entry point are all instructions. Each   of these instruct Docker to perform a specific  action while creating the image. Everything on the   right is an argument to those instructions. The  first line from Ubuntu defines what the base OS   should be for this container. Every Docker image  must be based off of another image, either an OS   or another image that was created before based  on an OS, you can find official releases of all   operating systems on Docker Hub. It's important  to note that all Docker files must start with the   from instruction. The run instruction instructs  Docker to run a particular command on those base   images. So at this point, Docker runs the abt get  update commands to fetch the updated packages,   and installs required dependencies on the image.  Then the copy instruction copies files from the   local system onto the Docker image. In this  case, the source code of our application is in   the current folder, and I'll be copying it over  to the location property source code inside the   Docker image. And finally, entry point allows  us to specify a command that will be run when   the image is run as a container. When Docker  builds the images, it builds these in a layered   architecture. Each line of instruction creates  a new layer in the Docker image with just the   changes from the previous layer. For example, the  first layer is a base Ubuntu OS, followed by the   second instruction that creates a second layer  which installs all the IPT packages. And then   the third instruction creates a third layer with  a Python packages followed by the fourth layer   that copies the source code over and the final  layer that updates the entry point of the image.   Since each layer only stores the changes from  the previous layer, it is reflected in the size   as well. If you look at the base Ubuntu image, it  is around 120 MB in size. The IPT packages that   are installed is around 300 Mb and the remaining  layers are small. You can see this information if   you run the Docker history command followed by the  image name. When you run the Docker build command,   you can see the various steps involved and the  result of each task. All the layers built are   cast. So the layered architecture helps you  restart Docker build from that particular step   in case it fails. Or if you were to add new steps  in the build process, you wouldn't have to start   all over again. All the layers built out cached by  Docker. So in case a particular step was to fail,   for example, in this case, step three failed, and  you were to fix the issue and rerun Docker build,   it will reuse the previous layers from  cache and continue to build the remaining   layers. The same is true if you were to add  additional steps in the Docker file. This way,   rebuilding your image is faster. And you don't  have to wait for Docker to rebuild the entire   image each time. This is helpful, especially when  you update source code of your application. As it   may change more frequently, only the layers above  the updated layers needs to be rebuilt. We just   saw a number of products containerized such as  databases, development tools, operating systems,   etc. But that's just not it. You can containerize  almost all of the application even simple ones,   like browsers or utilities, like curl  applications like Spotify, Skype,   etc. Basically, you can containerize everything  and going forward and see that's how everyone   is going to run applications. Nobody is going to  install anything anymore going forward. Instead,   they're just going to run it using Docker. And  when they don't need it anymore, get rid of it   easily without having to clean up too much. In  this lecture, we will look at commands arguments   and entry points in Docker. Let's start with a  simple scenario. Say you were to run a Docker   container from an Ubuntu image. When you run the  Docker run Ubuntu command it runs an instance of   Ubuntu image and exits immediately. If you were to  list the running containers, you wouldn't see the   container running. If you list all containers,  including those that are stopped, you will see   that the new container you ran is in an exited  state. Now why is that? Unlike virtual machines,   containers are not meant to host an operating  system. Containers are meant to run a specific   task or process, such as to host an instance of a  web server or application server or a database or   simply to carry out some kind of computation  or analysis. Once the task is complete, the   container exits a container only lives as long as  the process inside ID is alive. If the web service   inside the container is stopped or crashes, the  container exits. So who defines what process   is run within the container. If you look at the  Docker file for popular Docker images like ngi Nx,   you will see an instruction called CMD, which  stands for command that defines the program that   will be run within the container when it starts.  For the ngi nx image. It is the ngi nx command for   the MySQL image. It is the MySQL D command. What  we tried to do earlier was to run a container with   a plain Ubuntu Operating System. Let us look at  the Docker file for this image. You will see that   it uses bash as the default command. Now bash is  not really a process like a web server or database   server. It is a shell that listens for inputs  from a terminal. If it cannot find the terminal it   exits. When we ran the Ubuntu container earlier,  Docker created a container from the Ubuntu image   and launch the bash program. By default, Docker  does not attach a terminal to a container when   it is run. And so the bash program does not find  the terminal. And so it exits. Since the process   that was started when the container was created,  finished the container exits as well. So how   do you specify a different command to start the  container? One option is to append a command to   the Docker run command. And that way it overrides  the default command specified within the image.   In this case, I run the Docker run Ubuntu command  with the sleep five command as the added option.   This way when the container starts, it runs the  sleep program waits for five seconds and then   exits. But how do you make that change permanent?  Say you want the image to always run the sleep   command when it starts. You will then create  your own image from the base Ubuntu image and   specify a new command. There are different ways of  specifying the command either the command simply   as a In a shell form, or in a JSON array format  like this, but remember, when you specify in a   JSON array format, the first element in the array  should be the executable. In this case, the sleep   program did not specify the command and parameters  together like this, the command and its parameters   should be separate elements in the list. So I now  build my new image using the Docker build command,   and name it as a boon to sleeper. I could now  simply run the Docker boon to sleeper command and   get the same results. It always sleeps for five  seconds and exits. But what if I wish to change   the number of seconds it sleeps? Currently, it is  hard coded to five seconds. As we learned before,   One option is to run the Docker run command with  the new command appended to it, in this case,   sleep 10. And so the command that will be run  at startup will be sleep 10. But it doesn't look   very good. The name of the image, Ubuntu sleeper  in itself implies that the container will sleep,   so we shouldn't have to specify the sleep command  again. Instead, we would like it to be something   like this Docker run Ubuntu sleeper 10, we  only want to pass in the number of seconds the   container should sleep and sleep command should  be invoked automatically. And that is where the   entry point instruction comes into play. The entry  point instruction is like the command instruction.   As in, you can specify the program that will be  run when the container starts. And whatever you   specify on the command line, in this case, 10  will get appended to the entry point. So the   command that will be run when the container starts  is sleep 10. So that's the difference between the   two. In case of the CMD instruction, the command  line parameters passed will get replaced entirely.   Whereas in case of entry point, the command line  parameters will get appended. Now, in the second   case, what if I run the open to sleeper image  command without appending the number of seconds,   then the command at startup will be just sleep and  you get the error that the opposite is missing.   So how do you configure a default value for the  command if one was not specified in the command   line, that's where you would use both entry point  as well as the command instruction. In this case,   the command instruction will be appended to  the entry point instruction. So at startup, the   command would be sleep five, if you didn't specify  any parameters in the command line. If you did,   then that will override the command instruction.  And remember for this to happen, you should always   specify the entry point and command instructions  in a JSON format. Finally, what if you really   really want to modify the entry point during  runtime, say from sleep to an imaginary sleep 2.0   command? Well, in that case, you can override it  by using the entry point option in the Docker run   command. The final command at startup would then  be sleep 2.0 10. Well, that's it for this lecture,   and I will see you in the next. We now look at  networking in Docker. When you install Docker,   it creates three networks automatically. Bridge  no and host bridge is the default network a   container gets attached to if you would like to  associate the container with any other network,   specify the network information using the network  command line parameter like this. We will now look   at each of these networks. The bridge network is  a private internal network created by Docker on   the host all containers attached to this network  by default, and they get an internal IP address,   usually in the range 172 dot 17 series. The  containers can access each other using this   internal IP if required. To access any of these  containers from the outside world, map the ports   of these containers to port on the Docker host,  as we have seen before. Another way to access   the containers externally is to associate the  container to the host network. This takes out   any network isolation between the Docker host and  the Docker container. Meaning if you were to run   a web server on port 5000. In a web app container,  it is automatically as accessible on the same port   externally without requiring any port mapping  as the web container uses the hosts network.   This will also mean that unlike before, you will  now not be able to run multiple web containers on   the same host on the same port, as the ports  are now common to all containers in the host   network. With the non network, the containers  are not attached to any network and doesn't   have any access to the external network, or other  containers. They run in an isolated network. So   we just saw the default burst network where the  network ID 172 dot 70 dot 0.1. So all containers   associated to this default network will be able to  communicate to each other. But what if we wish to   isolate the containers within the Docker host, for  example, the first two web containers on internal   network 172 and the second two containers on a  different internal network, like 182. By default,   Docker only creates one internal bridge network,  we could create our own internal network using   the command Docker network, create and specify  the driver which is bridge in this case, and the   subnet for that network followed by the custom  isolated network name. Run the Docker network ls   command to list all networks. So how do we see the  network settings and the IP address assigned to an   existing container? Run the Docker inspect command  with the ID or name of the container, and you will   find a section on network settings. There you can  see the type of network the container is attached   to its internal IP address, MAC address, and other  settings. Containers can reach each other using   their names. For example, in this case, I have a  web server and a MySQL database container running   on the same node. How can I get my web server to  access the database on the database container. One   thing I could do is to use the internal IP address  signed to the MySQL container, which in this case   is 172 dot 70 dot 0.3. But that is not very ideal  because it is not guaranteed that the container   will get the same IP when the system reboots. The  right way to do it is to use the container name.   All containers in a Docker host can resolve each  other with the name of the container. Docker has   a built in DNS server that helps the containers  to resolve each other using the container name.   Note that the built in DNS server always runs at  address 127 dot 0.0 dot 11. So how does Docker   implement networking? What's the technology behind  it? Like how are the containers isolated within   the host? Docker uses network namespaces that  creates a separate namespace for each container.   It then uses virtual Ethernet pairs to connect  containers together. Well, that's all we can talk   about it for now. More about these are advanced  concepts that we discussed in the advanced course   on Docker on code cloud. That's all for now.  From this lecture on networking, head over to the   practice test and practice working with networking  in Docker. I will see you in the next lecture.   Hello and welcome to this lecture and we are  learning advanced Docker concepts. In this   lecture we're going to talk about Docker storage  drivers and file systems. We're going to see where   and how Docker stores data and how it manages  file systems of the containers. Let us start with   how Docker stores data on the local file system.  When you install Docker on a system, it creates   this folder structure at var lib Docker. You have  multiple folders under it called au Fs containers,   image volumes, etc. This is where Docker stores  all its data by default. When I say data, I mean   files related to images and containers running on  the Docker host. For example, all files related to   containers are stored under the containers folder.  And the files related to images are stored under   the image folder. Any volumes created by the  Docker containers. I created under the volumes   folder. Well, don't worry about that for now. We  will come back to that in a bit. For now, let's   just understand where Docker stores its files,  and in what format. So how exactly does Docker   store the files of an image and a container?  To understand that we need to understand   Dockers layered architecture. Let's quickly recap  something we learned when Docker builds images,   it builds these in a layered architecture. Each  line of instruction in the Docker file creates   a new layer in the Docker image with just the  changes from the previous layer. For example,   the first layer is a base Ubuntu Operating System,  followed by the second instruction that creates a   second layer, which installs all the Add packages.  And then the third instruction creates a third   layer, which with the Python packages, followed  by the fourth layer that copies the source code   over and then finally the fifth layer that  updates the entry point of the image. Since   each layer only stores the changes from the  previous layer, it is reflected in the size as   well. If you look at the base, a boon to image it  is around 120 megabytes in size. The abt packages   that are installed is around 300 Mb, and then  the remaining layers are small. To understand   the advantages of this layered architecture, let's  consider a second application. This application   has a different Docker file. But it's very similar  to our first application, as it uses the same base   image as Ubuntu uses the same Python and flask  dependencies, but uses a different source code   to create a different application. And so  a different entry point as well. When I run   the Docker build command to build a new image for  this application, since the first three layers of   both the applications are the same, Docker is not  going to build the first three layers. Instead,   it reuses the same three layers it built  for the first application from the cache,   and only creates the last two layers with the  new sources and the new entry point. This way,   Docker builds images faster and efficiently saves  disk space. This is also applicable if you were to   update your application code. Whenever you update  your application code, such as the app dot p y. In   this case, Docker simply reuses all the previous  layers from cash, and quickly rebuilds the   application image by updating the latest source  code, thus saving us a lot of time during rebuilds   and updates. Let's rearrange the layers bottom up  so we can understand it better. At the bottom we   have the base Ubuntu layer, then the packages,  then the dependencies, and then the source code   of the application, and then the entry point. All  of these layers are created when we run the Docker   build command to form the final Docker image. So  all of these are the Docker image layers. Once the   build is complete, you cannot modify the contents  of these layers and so they are read only and you   can only modify them by initiating a new build.  When you run a container based off of this image   using the Docker run command, Docker creates a  container based off of these layers and creates   a new writable layer on top of the image layer.  The writable layer is used to store data created   by the container, such as log files written by the  applications, any temporary files generated by the   container, or just any file modified by the user  on that container. The life of this layer though,   is only as long as the container is alive. When  the container is destroyed. This layer and all   of the changes stored in it are also destroyed.  Remember that the same image layer is shared by   all containers created using this image. If I were  to log into the newly created container and say,   create a new file called temp dot txt, it will  create that file in the container layer which is   read and write. We just said that the files in the  image layer are read only meaning you cannot edit   anything in those layers. Let's take an example of  our application code. Since we bake our code into   the image, the code is part of the image layer  and as such is read only after running a container   What if I wish to modify the source code to say  test to change. Remember, the same image layer may   be shared between multiple containers created from  this image. So does it mean that I cannot modify   this file inside the container. Now, I can still  modify this file. But before I save the modified   file, Docker automatically creates a copy of the  file in the readwrite layer, and I will then be   modifying a different version of the file in the  readwrite layer. All future modifications will   be done on this copy of the file in the readwrite  layer. This is called copy on write mechanism. The   image layer being read only just means that the  files in these layers will not be modified in the   image itself. So the image will remain the same  all the time, until you rebuild the image using   the Docker build command. What happens when we  get rid of the container, all of the data that was   stored in the container layer also gets deleted,  the changes we made to the app.pi and the new temp   file we created will also get removed. So what if  we wish to persist this data? For example, if we   were working with a database, and we would like  to preserve the data created by the container,   we could add a persistent volume to the container.  To do this, first create a volume using the Docker   volume create command. So when I run the Docker  volume create data underscore volume command,   it creates a folder called Data underscore volume  under the var lib Docker volumes directory. Then   when I run the Docker container using the Docker  run command, I could mount this volume inside   the Docker containers rewrite layer using the  dash v option like this. So I would do a Docker   run dash v then specify my newly created volume  name followed by a colon and the location inside   my container, which is the default location  where MySQL stores data and that is where lib   MySQL and then the image name MySQL. This will  create a new container and mount the data volume   we created into var lib MySQL folder inside the  container. So all data written by the database   is in fact stored on the volume created on the  Docker host. Even if the container is destroyed,   the data is still active. Now what if you didn't  run the Docker volume create command to create the   volume before the Docker run command. For example,  if I run the Docker run command to create a new   instance of MySQL container with the volume data  underscore Volume Two, which I have not created   yet, Docker will automatically create a volume  named data underscore Volume Two and mounted   to the container. You should be able to see all  these volumes if you list the contents of the var   lib Docker volumes folder. This is called volume  mounting. As we are mounting a volume created by   Docker under the var lib Docker volumes folder.  But what if we had our data already at another   location for example, let's say we have some  external storage on the Docker host at four   slash data. And we would like to store database  data on that volume and not in the default var lib   Docker volumes folder. In that case, we will run  a container using the command Docker run dash v.   But in this case, we will provide the complete  path to the folder we would like to mount that   is for slash data forward slash MySQL and so it  will create a container and mount the folder to   the container. This is called bind mounting. So  there are two types of mounts a volume mounting   and a bind mount volume mount mount a volume  from the volumes directory and bind mount mounts   a directory from any location on the Docker host.  One final point note before I let you go using the   dash V is an old style. The new way is to use dash  mount option. The dash dash mount is the preferred   way as it is more verbose. So you have to specify  each parameter in a key equals value format. For   example, the previous command can be written with  the dash mount option as this using the type,   source and target options. The type in this  case is bind. The source is the location on my   host and target is the location on my container.  So who He's responsible for doing all of these   operations, maintaining the layered architecture,  creating a writable layer moving files across   layers to enable, copy and write etc. It's the  storage drivers. So Docker uses storage drivers   to enable layered architecture. Some of the common  storage drivers are au Fs btrfs DFS device mapper   Overlay and overlay to the selection of the  storage driver depends on the underlying OS   being used, for example, with a boon to the  default storage driver is au Fs whereas this   storage driver is not available on other operating  systems like Fedora or CentOS. In that case,   device mapper may be a better option. Docker  will choose the best storage driver available   automatically based on the operating system. The  different storage drivers also provide different   performance and stability characteristics. So you  may want to choose one that fits the needs of your   application, and your organization. If you would  like to read more on any of these stories drivers,   please refer to the links in the  attached documentation. For now,   that is all from the Docker architecture concepts.  See you in the next lecture. Hello, and welcome to   this lecture on Docker compose. Going forward, we  will be working with configurations in yamo file,   so it is important that you are comfortable with  tmo. Let's recap a few things real quick course we   first learned how to run a Docker container using  the Docker run command. If we needed to set up a   complex application running multiple services, a  better way to do it is to use Docker compose with   Docker compose, we could create a configuration  file in yamo format called Docker compose dot yamo   and put together the different services and the  options specific to this to running them in this   file. Then we could simply run a Docker compose  up command to bring up the entire application   stack is easier to implement, run and maintain  as all changes are always stored in the Docker   compose configuration file. However, this is all  only applicable to running containers on a single   Docker host. And for now, don't worry about the  yamo file, we will take a closer look at the yamo   file in a bit and see how to put it together.  That was a really simple application that I   put together. Let us look at a better example.  I'm going to use the same sample application   that everyone uses to demonstrate Docker. It's  a simple yet comprehensive application developed   by Docker to demonstrate the various features  available in running an application stack on   Docker. So let's first get familiarized with the  application, because we will be working with the   same application in different sections through  the rest of this course. This is a sample voting   application which provides an interface for a user  to vote and another interface to show the results.   The application consists of various components  such as the voting app, which is a web application   developed in Python, to provide the user with  an interface to choose between two options,   a cat and the dog. When you make a selection,  the vote is stored in Redis. For those of you   who are new to Redis Redis, in this case serves as  a database in memory. This vote is then processed   by the worker which is an application written in  dotnet. The worker application takes the new vote   and updates the persistent database, which is  a Postgres SQL, in our case, the Postgres SQL   simply has a table with a number of votes for  each category, cats and dogs. In this case,   it increments the number of votes for cats as  our vote was for cats. Finally, the result of   the vote is displayed in a web interface, which is  another web application developed in Node JS. This   resulting application rates the count of votes  from the Postgres SQL database and displays it   to the user. So that is the architecture and  data flow of this simple voting application   stack. As you can see, this sample application is  built with a combination of different services,   different development tools, and multiple  different development platforms. So As Python,   no js, dotnet, etc. This sample application will  be used to showcase how easy it is to set up an   entire application stack consisting of diverse  components in Docker. Let us keep aside Docker   swarm services and stacks for a minute and see  how we can put together this application stack   on a single Docker engine using first Docker run  commands, and then Docker compose. Let us assume   that all images of applications are already  built and are available on Docker repository.   Let's start with the data layer. First, we run  the Docker run command to start an instance of   Redis. By running the Docker run Redis command,  we will add the dash D parameter to run this   container in the background. And we will also name  the container Redis. Now naming the containers is   important. Why is that important? Hold that  thought we will come to that in a bit. Next,   we will deploy the Postgres SQL database by  running the Docker run Postgres command. This   time too, we will add the dash D option to run  this in the background and name this container   DB for database. Next, we will start with the  application services. We will deploy a front end   app for voting interface by running an instance  of voting app image, run the Docker run command   and name the instance vote. Since this is a web  server, it has a web UI instance running on port   80. We will publish that port to 5000 on the host  system, so we can access it from a browser. Next,   we will deploy the result web application  that shows the results to the user. For this   we deploy a container using the results stash  app image and publish Port 80 to Port 5001 on   the host. This way, we can access the web UI  of the resulting app on a browser. Finally,   we deploy the worker by running an instance of  the worker image. Okay, now this is all good. And   we can see that all the instances are running on  the host. But there is some problem, it just does   not seem to work. The problem is that we have  successfully run all the different containers,   but we haven't actually linked them together. As  in we haven't told the voting web application to   use this particular Redis instance, there could  be multiple Redis instances running. We haven't   told the worker and the resulting app to use this  particular Postgres SQL database that we ran. So   how do we do that? That is where we use links.  Link is a command line option, which can be used   to link two containers together. For example, the  voting app web service is dependent on the Redis   service. When the web server starts, as you can  see, in this piece of code on the web server, it   looks for a Redis service running on host Redis.  But the voting app container cannot resolve a host   by the name Redis. To make the voting app aware  of the Redis service, we add a link option while   running the voting app container to link it to the  Redis container, adding a dash dash link option to   the Docker run command and specifying the name  of the Redis container which is which in this   case is Redis followed by a colon and the name  of the host that the voting app is looking for,   which is also Redis. In this case, remember that  this is why we named the container when we ran   it the first time so we could use its name while  creating a link. What this is, in fact doing is   it creates an entry into the EDC host file on  the voting app container, adding an entry with   the host name Redis with the internal IP of the  Redis container. Similarly, we add a link for   the result app to communicate with the database by  adding a link option to refer the database by the   name dB. As you can see, in this source code of  the application, it makes an attempt to connect   to a Postgres database on host dB. Finally, the  worker application requires access to both the   Redis as well as the Postgres database. So we  add two links to the worker application, one   link to link the Redis and the other link to link  Postgres database. Note that using links this way,   is deprecated and the support may be removed in  future in Docker. This is because as we will see   in some time Advanced and newer concepts in  Docker swarm and networking supports better   ways of achieving what we just did here with  links. But I wanted to mention it anyways, so   you learn the concept from the very basics. Once  we have the Docker run commands tested and ready,   it is easy to generate a Docker compose file from  it. We start by creating a dictionary of container   names, we will use the same name we used in the  Docker run commands. So we take all the names and   create a key with each of them. Then under each  item, we specify which image to use. The key is   the image and the value is the name of the image  to use. Next, inspect the commands and see what   are the other options used. We published ports.  So let's move those ports under the respective   containers. So we create a property called ports  and list all the ports that you would like to   publish under that. Finally, we are left with  links. So whichever container requires the link,   create a property under it called links and  provide an array of links such as Redis, or TP.   Note that you could also specify the name of the  link this way without the semicolon and and the   target target name, and it will create a link with  the same name as the target name. specifying the   DB colon DB is similar to simply specifying dB,  we will assume the same value to create a link.   Now that we're all done with our Docker compose  file, bringing up the stack is really simple from   the Docker compose up command to bring up the  entire application stack. When we looked at the   example of the sample voting application, we  assumed that all images are already built out   of the five different components. Two of them  Redis and Postgres images we know are already   available on Docker Hub. There are official images  from Redis and Postgres. But the remaining three   are our own application, it is not necessary  that they are already built and available in   the Docker registry. If we would like to instruct  Docker compose to run a Docker build, instead of   trying to pull an image, we can replace the image  line with a built line and specify the location   of a directory, which contains the application  code, and a Docker file with instructions to   build the Docker image. In this example, for the  voting app, I have all the application code in a   folder named vote which contains all application  code, and a Docker file. This time when you run   the Docker compose up command, it will first  build the images, give a temporary name for it,   and then use those images to run containers using  the options you specified before. Similarly use   build option to build the two other services  from the respective folders. We will now look   at different versions of Docker compose file. This  is important because you might see Docker compose   files in different formats at different places  and wonder why some look different. Docker compose   evolved over time, and now supports a lot more  options than it did in the beginning. For example,   this is the trimmed down version of the Docker  compose file we used earlier. This is in fact,   the original version of Docker compose file known  as version one. This had a number of limitations.   For example, if you wanted to deploy containers on  a different network other than the default bridge   network, there was no way of specifying  that in this version of the file. Also,   say you have a dependency or startup order of some  kind. For example, your database container must   come up first and only then I should the voting  application be started. There was no way you could   specify that in the version one of the Docker  compose file support for these came in version   two. With version two and up, the format of the  file also changed a little bit. You no longer   specify your stack information directly as you  did before. It is all encapsulated in Services   section. So create a property called services  in the root of the file, and then move all the   services underneath that. You will still use the  same Docker compose up command to bring up your   application stack. But how does Docker compose  know what version of the file you're using? You're   free to use version one or version two depending  on your needs. So how does the Docker compose,   know what format you're using. For version two  and up, you must specify the version of Docker   compose file you're intending to use by specifying  the version at the top of the file. In this case,   version, colon two. Another difference is with  networking. In version one, Docker compose   attaches all the containers, it runs to the  default bridged network. And then use links to   enable communication between the containers as  we did before. With version two Docker compose   automatically creates a dedicated bridged network  for this application, and then attaches all   containers to that new network. All containers are  then able to communicate to each other using each   other's service name. So you basically don't need  to use links in version two of Docker compose,   you can simply get rid of all the links you  mentioned in version one when you convert a   file from version one to version two. And finally,  motion to also introduces a depends on feature.   If you wish to specify a startup order. For  instance, say the voting web application is   dependent on the Redis service. So you need to  ensure that Redis container is started first,   and only then the voting web application must  be started. We could add a depends on property   to the voting application and indicate that it  is dependent on Redis. Then comes version three,   which is the latest as of today. version three  is similar to version two in the structure,   meaning it has a version specification at the top  and the Services section under which you put all   your services just like in version two, make sure  to specify the version number as three at the top.   version three comes with support for Docker swarm,  which we will see later on. There are some options   that were removed and added. To see details on  those you can refer to the documentation section   using the link in the reference page. Following  this lecture. We will see version three in much   detail later, when we discuss about Docker  stacks. Let's talk about networks in Docker   compose. Getting back to our application. So far,  we've been just deploying all containers on the   default bridge network. Let us say we modify the  architecture a little bit to contain the traffic   from the different sources. For example, we would  like to separate the user generated traffic from   the applications internal traffic. So we create  a front end network dedicated for traffic from   users, and a back end network dedicated for  traffic within the application. We then connect   the user facing applications which are the voting  app and the result app to the front end network   and all the components to an internal back end  network. So back in our Docker compose file,   note that I have actually stripped out  the port section for simplicity's sake,   there's still there, but they're just not shown  here. The first thing we need to do if we were   to use networks is to define the networks we are  going to use. In our case, we have two networks,   front end and back end. So create a new property  called networks at the root level, and listen to   the services in the Docker compose file and add  a map of networks we are planning to use. Then,   under each service, create a network's property  and provide a list of networks that service must   be attached to. In case of Redis and dB. It's  only the back end network. In case of the front   end applications such as the voting app and the  result app, they're required to be a test to both   a front end and back end network. You must also  add a section for worker container to be added   to the back end network. I have just omitted that  in this slide due to space constraints. Now that   you have seen Docker compose files, head over  to the coding exercises and practice developing   some Docker compose files. That's it for this  lecture. And I will see you in the next lecture.   We will now look at Docker registry. So what is  a registry if the containers Where the rain then   they will rain from the Docker registry, which  are the clouds. That's where Docker images are   stored. It's a central repository of all Docker  images. Let's look at a simple nginx container.   We run the Docker run nginx command to run  an instance of the nginx image. Let's take a   closer look at that image name. Now the name is  nginx. But what is this image and where is this   image pulled from? This name follows Dockers image  naming convention nginx. Here is the image or the   repository name. When you say nginx, it's actually  nginx slash nginx. The first part stands for the   user or account name. So if you don't provide an  account or a repository name, it assumes that it   is the same as the given name, which in this case  is nginx. The usernames is usually your Docker   Hub account name or if it is an organization,  then it's the name of the organization. If you   were to create your own account and create  your own repositories or images under it,   then you would use a similar pattern. Now, where  are these images stored and pulled from? Since   we have not specified the location where these  images are to be pulled from, it is assumed to be   on Dockers default registry, Docker Hub, the DNS  name for which is docker.io. The registry is where   all the images are stored. Whenever you create a  new image or update an existing image, you push   it to the registry and every time anyone deploys  this application, it is pulled from that registry.   There are many other popular registries as well.  For example, Google's registry is that dcr.io,   where a lot of Kubernetes related images are  stored, like the ones used for performing end to   end tests on the cluster. These are all publicly  accessible images that anyone can download,   and access. When you have applications built in  house that shouldn't be made available to the   public. hosting an internal private registry may  be a good solution. Many cloud service providers   such as AWS, Azure, or GCP, provide a private  registry by default, when you open an account with   them. on any of these solutions via Docker Hub, or  Google registry or your internal private registry,   you may choose to make a repository private,  so that it can only be accessed using a set   of credentials from Dockers perspective. To run a  container using an image from a private registry.   you first log into your private registry using  the Docker login command, input your credentials.   Once successful, run the application using private  registry as part of the image name like this. Now,   if you did not log into the private registry, it  will come back saying that the image cannot be   found. So remember to always log in before pulling  or pushing to a private registry. We said that   cloud providers like AWS or GCP provide a private  registry when you create an account with them.   But what if you're running your application on  premise and don't have a private registry? How do   you deploy your own private registry within your  organization, the Docker registry, itself another   application, and of course, is available as a  Docker image. The name of the image is registry,   and it exposes the API on port 5000. Now that you  have your custom registry running at Port 5000,   on this Docker host, how do you push your own  image to it? Use the Docker image tag command   to tag the image with the private registry URL  in it. In this case, since it's running on the   same Docker host, I can use local host semi colon  5000 followed by the image name. I can then push   my image to my local private registry using the  command Docker push and the new image name with   the Docker registry information in it. From there  on, I can pull my image from anywhere within this   network using either localhost if you're on the  same host, or the IP or domain name of my Docker   host, if I'm accessing from another host in my  environment. Well, that's it for this lecture,   head over to the practice test and practice  working with private Docker registries.   Welcome to this lecture on Docker engine.  In this lecture, we will take a deeper look   at Dockers architecture, how it actually runs  applications in isolated containers and how it   works under the hood. Docker engine as we have  learned before you simply refer to a host with   Docker installed on it. When you install Docker  on a Linux host, you're actually installing three   different components. The Docker daemon, the REST  API server, and the Docker CLA. The Docker daemon   is a background process that manages Docker  objects such as the images, containers, volumes   and networks. The Docker REST API server is the  API interface that programs can use to talk to the   daemon and provide instructions, you could create  your own tools using this REST API. And the Docker   CLA is nothing but the command line interface  that we've been using, until now to perform   actions such as running a container stopping  containers, destroying images, etc. It uses   the REST API to interact with the Docker daemon.  Something to note here is that the Docker CLA need   not necessarily be on the same host. It could be  on another system like a laptop, and can still   work with a remote Docker engine. Simply use the  dash H option on the Docker command and specify   the remote Docker engine address and a port  as shown here. For example, to run a container   based on nginx on a remote Docker host, run the  command Docker dash H equals 10.1 23 dot 2.1 colon   2375 run ngi nx. Now let's try and understand how  exactly our applications containerized in Docker,   how does it work under the hood, Docker uses  namespaces to isolate workspace, process IDs,   network, inter process communication, mounds  and Unix time sharing systems are created in   their own namespace thereby providing isolation  between containers. Let's take a look at one of   the namespace isolation technique. process ID  namespaces. Whenever a Linux system boots up,   it starts with just one process with a process  ID of one. This is the root process and kicks   off all the other processes in the system.  By the time the system boots up completely,   we have a handful of processes running. This can  be seen by running the PS command to list all the   running processes. The process IDs are unique  and two processes cannot have the same process   ID. Now if we were to create a container, which is  basically like a child system within the current   system, the child system needs to think that it  is an independent system on its own. And it has   its own set of processes originating from a root  process with a process ID of one. But we know that   there is no hard isolation between the containers  and the underlying host. So the processes running   inside the container are in fact processes running  on the underlying host. And so two processes   cannot have the same process ID of one. This is  where namespaces come into play. With process   ID namespaces. Each process can have multiple  process IDs associated with it. For example,   when the processes start in the container, it's  actually just another set of processes on the   base Linux system. And it gets the next available  process ID in this case, five and six. However,   they also get another process ID starting with P  ID one in the container namespace which is only   visible inside the container. So the container  things that it has its own route process tree. And   so it is an independent system. So how does that  relate to an actual system? How do you see this on   a host? Let's say I were to run an nga next server  as a container. We know that the nginx container   runs and nginx service. If we were to list all the  services inside the Docker container, we see that   the next service running with a process ID of one.  This is the process ID of the service inside of   the container namespace. If we list the services  on the Docker host, we will see the same service   but with a different process ID that indicates  that all processes are in fact running on the same   host but separated into their own containers using  namespaces. So we learned that the underlying   Docker host as well as the containers share the  same system resources such as CPU and memory. How   much of the resources are dedicated to the host  and the containers? And how does Docker manage   and share the resources between the containers.  By default, there is no restriction as to how   much of a resource a container can use. And  hence, a container may end up utilizing all   of the resources on the underlying host. But there  is a way to restrict the amount of CPU or memory   a container can use. Docker uses thi groups or  control groups to restrict the amount of hardware   resources allocated to each container. This can  be done by providing the dash dash CPUs option   to the Docker run command. Providing a value of  point five will ensure that the container does   not take up more than 50% of the host CPU at any  given time. The same goes with memory. Setting a   value of 100 M to the dash dash memory option  limits the amount of memory the container can   use to 100 megabytes. If you're interested in  reading more on this topic, refer to the links   I posted in the reference page. That's it for now  on Docker engine. In the next lecture, we talked   about other advanced topics on Docker storage and  file systems. See you in the next lecture. During   this course, we learned that containers share the  underlying OS kernel. And as a result, we cannot   have a Windows container running on Linux hosts  or vice versa. We need to keep this in mind while   going through this lecture, as it's very important  concept and most beginners tend to have an issue   with it. So what are the options available  for Docker on Windows? There are two options   available. The first one is Docker on Windows  using Docker toolbox. And the second one is the   Docker desktop for Windows option. We will look at  each of these now. Let's take a look at the first   option. Docker toolbox. This was the original  support for Docker on Windows. Imagine that you   have a Windows laptop and no access to any Linux  system whatsoever. But you would like to try   Docker, you don't have access to a Linux system in  the lab or in the cloud. What would you do? What   I did was to install a virtualization software  on my Windows system like Oracle VirtualBox or   VMware Workstation and deploy a Linux VM on it  such as Ubuntu or Debian, then install Docker on   the Linux VM and then play around with it. This  is what the first option really does. It doesn't   really have anything much to do with Windows,  you cannot create Windows based Docker images,   or run Windows based Docker containers. You  obviously cannot run Linux container directly on   Windows either. You're just working with Docker on  a Linux virtual machine on a Windows host. Docker,   however, provides us with a set of tools to make  this easy which is called as the Docker toolbox.   The Docker toolbox contains a set of tools like  Oracle VirtualBox, Docker engine, Docker machine,   Docker compose and a user interface called  kite Matic. This will help you get started   by simply downloading and running the Docker  toolbox executable. Ever install VirtualBox,   deploy a lightweight VM called boot to Docker,  which has Docker running in it already so that   you are all set to start with Docker easily  and with within a short period of time. Now   what about requirements, you must ensure that  your operating system is 64 bit Windows seven   or higher and that the virtualization  is enabled on the system. Now remember,   Docker toolbox is legacy version for older  Windows systems that do not meet requirements   for the newer Docker for Windows option. The  second option is the newer option called Docker   desktop for Windows. In the previous option,  we saw that we had Oracle VirtualBox installed   on Windows and then a Linux system and then Docker  on that Linux system. Now with Docker for Windows,   we take out Oracle VirtualBox and use the native  virtualization technology available with Windows   called Microsoft Hyper V. During the installation  process for Docker for Windows, it will still   automatically create a Linux system underneath.  But this time it is created on the Microsoft Hyper   V instead of Oracle VirtualBox and have Docker  running on that system. Because of this dependency   on Hyper V. This option is only supported for  Windows 10 Enterprise or Professional Edition   and on Windows Server 2016. Because both  these operating systems come with Hyper V   support by default. Now here's the most important  point. So far whatever we've been discussing,   with Dockers support for Windows. It is strictly  for Linux containers, Linux applications packaged   into Linux Docker images. We're not talking  about Windows applications. Windows images   or Windows containers. Both the options we just  discussed will help you run a Linux container on a   Windows host. With Windows Server 2016, Microsoft  announced support for Windows containers for the   first time. You can now package applications  Windows applications into Windows Docker   containers and run them on a Windows Docker host  using Docker desktop for Windows. When you install   Docker desktop for Windows, the default option  is to work with Linux containers. But if you   would like to run Windows containers, then you  must explicitly configure Docker for Windows to   switch to using Windows containers. In early  2016, Microsoft announced windows containers.   Now you could create Windows based images and  run Windows containers on a Windows Server just   like how you would run Linux containers on a  Linux system. You can create windows images,   containerize your applications and share them  through the Docker store as well. Unlike in Linux,   there are two types of containers in Windows. The  first one is a Windows Server container, which   works exactly like Linux containers where the OS  kernel is shared with the underlying operating   system to allow better security boundary between  containers and to have kernels with different   versions and configurations to coexist. The  second option was introduced known as the Hyper   V isolation. With Hyper V isolation each container  is run within a highly optimized virtual machine   guaranteeing complete kernel isolation between the  containers and the underlying host. Now while in   the Linux world, you had a number of base images  for Linux systems such as Ubuntu, Debian, Fedora,   Alpine etc. If you remember that, that is what you  specify at the beginning of the Docker file. In   the windows world, we have two options the Windows  Server Core and Nano Server. A Nano Server is a   headless deployment option for Windows Server  which runs at a fraction of size of the full   operating system. You can think of this like the  Alpine image in Linux. The Windows Server Core,   though is not as light weight as you might  expect it to be. Finally, Windows containers   are supported on Windows Server 2016 Nano  Server and Windows 10 professional Enterprise   Edition. Remember on Windows 10 professional  and Enterprise Edition only supports Hyper V   isolated containers. Meaning as we just discussed,  every container deployed is deployed on a highly   optimized virtual machine. Well, that's it about  Docker on Windows. Now before I finish, I want to   point out one important fact. We saw two ways of  running a Docker container using VirtualBox or   Hyper V. But remember, VirtualBox and Hyper  V cannot coexist on the same windows host.   So if you started off with Docker toolbox with  VirtualBox and if you plan to migrate to Hyper V,   remember you cannot have both solutions at the  same time. There is a migration guide available   on Docker documentation page on how to migrate  from VirtualBox to Hyper V. That's it for now.   Thank you and I will see you the next lecture. We  now look at Docker on Mac Docker on Mac is similar   to Docker on Windows. There are two options to  get started Docker on Mac using Docker toolbox,   or Docker desktop for Mac option. Let's look at  the first option. Docker toolbox. This was the   original support for Docker on Mac. It is Docker  on Linux VM created using VirtualBox on Mac as   Windows It has nothing to do with Mac applications  or Mac based images or Mac containers. It purely   runs Linux containers on a Mac OS. Docker toolbox  contains a set of tools like Oracle VirtualBox,   Docker engine, Docker machine, Docker compose,  and a user interface called cadmatic. When you   download and install the Docker toolbox  executable, installs VirtualBox deploys   lightweight VM called boot to Docker, which has  Docker running in it already. This requires mac   os 10.8 or newer. The second option is the newer  option called Docker desktop for Mac with Docker   desktop for Mac, we take out Oracle VirtualBox  and use hypercard virtualization technology   during the installation process for Docker for  Mac, it will still automatically create a Linux   system underneath. But this time it is created on  hypercard instead of Oracle VirtualBox and have   Docker running on that system. This requires Mac  OS Sierra 10 or 12 or newer, and my and the Mac   hardware must be 2010 or newer. Finally, remember  that all of this is to be able to run the Linux   container on Mac. As of this recording, there are  no Mac based images or containers. Well, that's it   with Docker on Mac for now. We will now try to  understand what container orchestration is. So   far in this course, we have seen that with Docker,  you can run a single instance of the application   with a simple Docker run command. In this case,  to run a Node JS based application, you run the   Docker run node j s command. But that's just one  instance of your application on one Docker host,   what happens when the number of users increase,  and that instance is no longer able to handle the   load, you deploy additional instance of your  application by running the Docker run command   multiple times. So that's something you have to  do yourself, you have to keep a close watch on   the load and performance of your application and  deploy additional instances yourself. And not just   that, you have to keep a close watch on the health  of these applications. If a container was to fail,   you should be able to detect that and run the  Docker run command again to deploy another   instance of that application. What about the  health of the Docker host itself? What if the host   crashes and is inaccessible? The containers hosted  on that host become inaccessible to so what do you   do in order to solve these issues, you will need  a dedicated engineer who can sit and monitor the   state performance and health of the containers and  take necessary actions to remediate the situation.   But when you have large applications deployed  with 10s of 1000s of containers that that's   not a practical approach. So you can build your  own scripts. And that will help you tackle these   issues. To some extent. container orchestration  is just a solution for that. It is a solution   that consists of a set of tools and scripts  that can help host containers in a production   environment. Typically, a container orchestration  solution consists of multiple Docker hosts that   can host containers. That way, even if one fails,  the application is still accessible through the   others. A container orchestration solution  easily allows you to deploy hundreds or 1000s   of instances of your application with a single  command. This is a command used for Docker swarm,   we will look at the command itself in a bit. Some  orchestration solutions can help you automatically   scale up the number of instances when users  increase and scale down the number of instances   when the demand decreases. Some solutions can even  help you in automatically adding additional hosts   to support the user load, and not just clustering  and scaling. The container orchestration solutions   also provide support for advanced networking  between these containers across different hosts,   as well as load balancing user requests across  different house. They also provide support for   sharing storage between the house as well as  support for configuration management and security   within the cluster. There are multiple container  orchestration solutions available today. Docker   has Docker swarm Kubernetes from Google and mezzos  from patchy while Docker swarm is really easy to   set up and get started. It lacks some of the  advanced auto scaling features required for   complex production grade applications. mezzos on  the other hand, is quite difficult to set up and   get started, but supports many advanced features.  Kubernetes is arguably the most popular of it all   is a bit difficult to set up and get started but  provides a lot of options to customize deployments   and has support for many different vendors.  Kubernetes is now supported on all public cloud   service providers like GCP, Azure and AWS and  the Kubernetes project is one of the top ranked   projects on GitHub and upcoming lectures. We will  take a quick look at Docker swarm and Kubernetes.   We will now get a quick introduction to Docker  swarm. Docker swarm has a lot of concepts to   cover and requires its own course. But we will  try to take a quick look at some of the basic   details so you can get a brief idea on what it is.  with Docker swarm. You could now combine multiple   Docker machines together into a single cluster.  Docker swarm will take care of distributing your   services or your application instances into  separate hosts for high availability For load   balancing across different systems and hardware  to set up a Docker swarm, you must first have   hosts or multiple hosts with Docker installed on  them, then you must designate one host to be the   manager or the master or the swarm manager as it  is called, and others as slaves or workers. Once   you're done with that, run the Docker swarm in  it command on the swarm manager, and that will   initialize the swarm manager. The output will also  provide the command to be run on the workers to   copy the command and run it on the worker nodes  to join the manager. After joining the swarm,   the workers are also referred to as nodes. And  you're now ready to create services and deploy   them on the swarm cluster. So let's get into  some more details. As you already know, to run   an instance of my web server, I run the Docker run  command and specify the name of the image I wish   to run. This creates a new container instance of  my application and serves my web server. Now that   we have learned how to create a swarm cluster, how  do I utilize my cluster to run multiple instances   of my web server. Now one way to do this would  be to run the Docker run command on each worker   node. But that's not ideal as I might have to log  into each node and run this command. And there,   there could be hundreds of nodes that will have  to set up load balancing myself, I like to monitor   the state of each instance myself. And if  instances were to fail, I'll have to restart them   myself. So it's going to be an impossible task.  And that is where Docker swarm orchestration comes   in. Docker swarm orchestrator does all of this for  us. So far, we've only set up the swarm cluster,   but we haven't seen orchestration in action.  The key component of swarm orchestration is   the Docker a service. Docker services are one or  more instances of a single application or service   that runs across the saw the nodes in the swarm  cluster for example. In this case, I could create   a Docker service to run multiple instances of my  web server application across worker nodes in my   swarm cluster. For this, I run the Docker service,  create command on the manager node and specify my   image name there, which is my web server in this  case, and use the option replicas to specify the   number of instances of my web server I would like  to run across the cluster, since I specified three   replicas, and I get three instances of my web  server distributed across the different worker   nodes. Remember, the Docker service command  must be run on the manager node and not on the   worker node. The Docker service create command is  similar to the Docker run command in terms of the   options passed, such as the dash e environment  variable, the dash p for publishing ports,   the network option to attach container to  a network, etc. Well, that's a high level   introduction to Docker swarm, there is a lot more  To know such as configuring multiple managers,   overlay networks, etc. As I mentioned, it requires  its own separate course. Well, that's it for now.   In the next lecture, we will look at Kubernetes at  a high level. We will now get a brief introduction   to basic Kubernetes concepts. Again Kubernetes  requires its own course, well, a few courses,   at least five, but we will try to get a brief  introduction to it here. with Docker, you were   able to run a single instance of an application  using the Docker COI by running the Docker run   command, which is great. running an application  has never been so easy before. with Kubernetes   using the Kubernetes COI, known as cube control,  you can run 1000 instances of the same application   with a single command Kubernetes can scale it up  to 2000 with another command Kubernetes can be   even configured to do this automatically so that  instances and the infrastructure itself can scale   up and down. based on user load Kubernetes can  upgrade these 2000 instances of the application   in a rolling upgrade fashion, one at a time  with a single command. If something goes wrong,   it can help you roll back these images with a  single command Kubernetes can help you test new   features of your application. By only upgrading  a percentage of these instances through a B   testing methods. The Kubernetes open architecture  provides support for many, many different network   and storage vendors. Any network or storage brand  that you can think of has a plugin for Kubernetes   Kubernetes supports a variety of authentication  and authorization mechanisms. All major cloud   service providers have native support for  Kubernetes. So what's the relation between   Docker and Kubernetes Kubernetes uses Docker  host to host applications in the form of Docker   containers. Well, it need not be Docker all the  time. Kubernetes supports as natives to Dockers as   well, such as rocket, or a crier. But let's take  a quick look at the Kubernetes architecture. A   Kubernetes cluster consists of a set of nodes, let  us start with nodes. A node is a machine physical   or virtual on which a Kubernetes the Kubernetes  software set of tools are installed. And node is a   worker machine. And that is where containers will  be launched by Kubernetes. But what if the node   on which the application is running fails? Well,  obviously, our application goes down. So you need   to have more than one nodes. A cluster is a set of  nodes grouped together this way, even if one node   fails, you have your application still accessible  from the other nodes. Now we have a cluster but   who is responsible for managing this cluster?  Where is the information about the members of   the cluster stored? How are the nodes monitored?  When a node fails? How do you move the workload of   the failed nodes to another worker node, that's  where the master comes in. The Master is a node   with the Kubernetes control plane components  installed. The master watches over the notes are   in the cluster and is responsible for the actual  orchestration of containers on the worker nodes.   When you install Kubernetes on a system, you're  actually installing the following components,   an API server and actually server, a cubelet  service container runtime engine like Docker, and   a bunch of controllers and the scheduler. The API  server acts as the front end for Kubernetes. The   users management devices command line interfaces  all talk to the API server to interact with the   Kubernetes cluster. Next is the Etsy d a key value  store. The Etsy D is a distributed reliable key   value store used by Kubernetes to store all data  used to manage the cluster. Think of it this way,   when you have multiple nodes and multiple  masters in your cluster. etsy D stores all   that information on all the nodes in the cluster  in a distributed manner. NCD is responsible for   implementing a locks within the cluster to ensure  there are no conflicts between the masters. The   scheduler is responsible for distributing work  or containers across multiple nodes. It looks   for newly created containers and assigns them  to nodes. The controllers are the brain behind   orchestration, they're responsible for noticing  and responding when nodes containers or endpoints   goes down. The controllers makes decisions  to bring up new containers. In such cases,   the container runtime is the underlying software  that is used to run containers. In our case,   it happens to be Docker. And finally, cubelet is  the agent that runs on each node in the cluster.   The agent is responsible for making sure that the  containers are running on the nodes as expected.   And finally, we also need to learn a little bit  about one of the command line utilities known   as the cube command line tool or the cube control  tool or cube cuddle as it is also called the cube   control tool is the Kubernetes CLA, which is used  to deploy and manage applications on a Kubernetes   cluster to get cluster related information to get  the status of the nodes in the cluster, and many   other things. The Cube control run command is  used to deploy an application on the cluster.   The Cube control cluster info command is used to  view information about the cluster. And the cube   control get nodes command is used to list all the  nodes part of the cluster. So to run hundreds of   instances of your application across hundreds  of nodes. All I need is a single Kubernetes   command like this. Well, that's all we have for  now, a quick introduction to Kubernetes and its   architecture. We currently have three courses on  code cloud on Kubernetes that will take you from   the absolute beginner to a certified expert.  So have a look at it when you get a chance.   So we're at the end of this beginner's course  to Docker. I hope you had a great learning   experience. If so please leave a comment  below. If you'd like my way of teaching,   you will love my other courses hosted on my site  at code cloud. We have courses for Docker swarm   Kubernetes advanced courses on Kubernetes  certification, as well as openshift. We have   courses for automation tools like Ansible  Chef and Puppet and many more on the way,   visit code cloud@www.cloud.com. Well, thank you so  much for your time, and until next time, goodbye.