Docker Full Course 2026

#Docker
💬 Chat with this Video
Ask anything about this video…
Ever wondered how tech giants like Spotify and Netflix scale their software so fast? The secret is containerization with Docker as the essential tool at its core. This structured hands-on Docker course will take you from absolute beginner to job ready, providing the practical skills needed to build, test, and deploy containerized applications reliably. Isa from Dolphin Ed created this course. Have you ever wondered how tech giants like Spotify, Amazon and Netflix, they ship software faster and they scale instantly? The secret is containerization and Docker at the heart of it. In today's IT world, Docker is everywhere from startups to tech giants and Inc. 500 companies and it is the core tool or the containerization is the core tool behind cloud devops software development modern security roles and modern application architectures. Docker has become the gold standard when it comes to shipping and deploying applications that run efficiently and reliably in the cloud or on premises. The industry is shifting so fast. Companies are containerizing all the applications or the legacy applications that they can and maybe shifting that also to the cloud and Docker has become a primary skill in that revolution. Learning Docker now means you are not just keeping up but you are getting ahead and also learning Docker now is going to pave the way for you to learn Kubernetes the gold standard when it comes to orchestration and management of containers at scale. Whether you are an IT fresher switching into IT or an existing IT professional upskilling, this course is your complete structured stepbystep practical guide to mastering Docker. And the course will take you from the absolute scratch to becoming job ready using Docker in deploying applications and services. The course will start from the very basics from comparing virtual machines to containers. Why do we need containers and how Docker transforms the way we build and deploy applications? Then we'll dive deeper into Docker by learning what is a Docker file and how we can create an image from a Docker file and how we can deal with Docker Hub and build repos where we can ship the created images and then understanding and working with Docker networking storage and volumes and then deploying multi-container applications using Docker Compose and it doesn't stop there but it will take you further to introduce what Docker Swarm is which is an Orchestration management for Docker containerized applications by Docker. The course is hands-on, practical, learn by doing, basically creating Docker files and images and containers and applications and browsing to them and Docker Compose and writing YAML files and much more. By doing all of this with quizzes and assignments in the respective modules and real world projects at the end, this is all what you need to go from zero to hero in Docker. By the end of this course, you will walk away confident to build, test, and deploy containerized applications using Docker and Docker Compose and will be ready to deploy these real world skills in any IT role that requires these skills. My name is Isa Abu Sharif and I have been in IT for more than 25 years now. I am an AWS certified instructor and I am a Cisco certified instructor since 2005. I hold many IT certifications and infrastructure certifications as well including the Cisco certified internet network expert. I have been teaching for more than 21 years now as a certified instructor and I have taught networking and I have taught management and I have taught uh infrastructure cloud and automation and devops courses and in addition to that I have also been in the IT industry myself as an architect as a consultant at IBM in the US and at Cisco and other companies. So I have blended all of that experience to explain to you in layman terms very easily from the ground up what containerization is, why do we need it and how we can work with it. So that at the end of the course you will be able to work confidently with docker and that would be the a stepping stone for you to learn kubernetes which is orchestration and management for containerized applications at scale. So you will not be bored and you will be entertained throughout the course. It's going to be engaging and not boring. I promise. And at the end you will be proud of the time you have invested in this course. This course would never be possible without your support. In order to support us develop more free content that is high quality at no price to you like this one, consider buying the full package of this course on www.dolphined.com. It can be found at this address www.dolphinet.com/courses/doccker. Very easy URL to follow. And for a price of a lunch or even less with the inflation that we are living in right now, you can support us develop more free and quality content like this one to help you throughout your learning journey and to help the masses as well across the globe. If you buy the full VIP package, as I like to call it, you're going to have lifetime access to the content and its updates. It's going to be split into video lectures. So you don't have to be overwhelmed with seven or eight hours or even 15 hours a single video. You can have that divided into separate lectures for theory and hands-on. You are going to have access to the full 15 hours version of this course. And you're going also to have additional hands-on labs on the topics that we have covered. But at at a deeper level, you'll have a second realworld capstone project that will deepen your real world experience with Docker. And also you'll have a community access to that community for faster Q&A support. And of course, the ability on our platform to have quizzes and assignments is going to be there as well. And also you'll have access to the scripts for all the hands-on labs and the 330 pages PDF guide that includes all the slides of this course. We appreciate your support if you can and that would definitely be a good return on investment to yourself as well through more free content that we can generate through your support. In this course, we are going to cover the following topics. We're going to introduce what Docker is and why do we need containers and how they are different from physical servers and virtual machines. Then I'm going to take you to set up Docker on a free virtual machine, Linux virtual machine on AWS. So I will teach you how to create AWS account and whatever you are going to do is going to be free. So you don't have to bother about installing on your laptop or creating virtual machines on your laptop and at the same time you will be practicing what you will do in the real job if you like to practice Docker with confidence. Then I'm going to take you to what Docker is and the architecture of Docker. Then we are going to move on and start to learn docker commands and how to use that to create containers of different use cases with different base images. Then I will explain to you how we can create a container from an image. I'll take you to docker hub and explain to you that there is a repository of free available images that you can just download and create containers from. And I will also teach you what if you have an application that doesn't have an image and you would like to run it in containers. So how you can containerize that through docker files. From there we're going to jump into docker registries. So now in your corporate if you are the master of docker and you are creating containers for your company. Now where do you store them? What's the repo repository or the registry as we call it in docker that you can upload your images to? And it's up to you. You can make them public so anybody can benefit from them or you can make them in a private registry where only the corporate members that have access to that repo will be able to login authenticate and download that to create containers from. Then we are going to introduce the docker networking and how can that be used how you can access the containers from the outside and we are going to look at docker compose and how we can automate the process. Instead of doing that manually, we are going to get into how we can write YAML configuration files for compose where you can do that automatically through compose. Then we are going to look at persisting data in your containers. What if the container dies? It's just a software process as we learn. What if it dies? I lose all the data. What if it was a database and it has very critical data? What do I do? Then how we can persist the data by mounting volumes or bind mounts outside the container. So if the container dies I can create another one that attaches to the same data or I can make the data available to multiple containers at the same time. From there we are going to work on a project real world project where you will you are going to deploy what you have learned and you are going to understand better how this works how this containerization of application or microservices happens and from there we are going to wrap up and I assure you that you will be confident at the end and you are going to use docker with comfort. So whether you are a fresher into IT or someone changing career into IT or you are already into IT but you don't know Docker, you have to learn it now. So without further ado, let's get started. Why do we need to learn Docker and why Docker? Why is what is so special about Docker that we need to learn it? So, Stack Overflow in 2024 did a survey and asking the contributor or those who contributed to the survey what are the most popular developer tools that they are commonly using or they prefer to use. And as you can see over here that Docker was at the top with a 50 plus% and this is number one like this was voted the two number one by 53 point something of the contributors or the respondents the survey. Now if we think what about if we send out a survey and we get the feedback which are the top three tools do you think the ones that will include Docker as number one or two or three are going to jump to maybe 70 80% and I truly believe it might be even higher than that one might ask okay but these are developers machine learning ops engineer or maybe I'm an AI engineer maybe I'm a data scientist or a data analyst or maybe I'm a cloud engineer you might I think this is not relevant to me. We just picked developers. Actually, Docker applies to all IT professions nowadays from the simple automation all the way to hosting applications at a large scale. So containers are in the heart of that. Of course, Kubernetes when we are talking about a very large scale deployment would be the right thing to do, but Docker and Docker based applications and environments and clusters are very common as well. if the scale is not that large and the complexity required or desired is not high as well. So why do what is so special about it? Why are developers loving it? And why do everyone have to learn it? It has a lot of features but among these the top four are environment reproducibility. So you can recreate what you do on your laptop if you follow the same steps. You can recreate it in production, in development, in testing, in the cloud or on your laptop or on premises. Same result. If you follow the same instructions and the same steps, you get exactly the same result, which is excellent and amazing because last thing you want to do is developers work on an environment. When you try to recreate that environment, then you have differences and then when you test, then you get problems. But the developer will tell you it works on my machine. That is why Docker was invented. We don't want to listen to it works on my machine then it should be your problem. Then you take it from testing into production and then you have more issues. So reproducibility in Docker is top-notch. Second one is dependency management. you have multiple things on the virtual machine or the server, multiple applications and some tool requires Python version 2.7 whereas the application that is built by Flask needs Python 3.8 or 3.9 then now we might start to get into conflicts and dependency management is a very important thing when we are developing software and tools and applications. So dependency management is very easy in Docker and we're going to explain why. Portability is very easy when you are dealing with containers and with Docker as an example and that is very important because today I'm on AWS tomorrow I'm going to be on premises or maybe I'm going to move to Azure or maybe I need to replicate my environment in Google cloud then in that case portability is very key and hopefully the size of the data that has to do with my application is not very large. So I can just transfer it maybe in 10 15 minutes and start working on it or maybe I ship it somewhere on the cloud and pull it from the other side. So portability is key and this is very very important when it comes to working with applications and modern applications to be more specific. Last but not least on the top four reasons why Docker is very popular is the fact that when you deal with Docker configurations are scripted in text files. So it's very easy to track them. It's very easy to have them on GitHub and then you can track the different versions and what changed between every minor version to the next or maybe every minor to a major release and why were the changes done. uh we added this database we updated to um engine X version X and Y and Z we did Ubuntu version 20.04 04. So you can track the changes and it's very easy to roll back if needed or to go back in history and find out. Okay, so why do we have an issue now and we didn't have that before. So version control is very key. So these are the four top reasons why you need to learn Docker and you need to do it right now. where the technology started and we'll go back into the physical servers era and then we'll take it through virtualization. Why are we doing this? Because if you are a newcomer into IT or shifting into IT or you haven't dealt with servers and virtual machines and all that before it makes a lot of sense to give you a brief of what used to happen and why did we get into containers. So this is going to be your introduction into that. If you are a well seasoned professional and know what virtual machines are and what physical servers and data centers and all that then you can skip this section and move to the next one. So let's start by finding out what is common between the different computing devices. And when we talk about computing device, could be a server, could be your laptop, could be an iPad, could be your phone, it could be any digital device that is functioning at your home or in the office or maybe in the malls and so on. Any comput device components will have a number of components. Any computing any computing device will have a number of components, but the most common ones are it will have a CPU. It will have the engine that can process everything that comes to it, instructions, programs, applications, Microsoft Word, Excel and so on. So the CPU is the central processing unit or you can say that it is the one that does the work. Then we have random access memory and that's called the RAM. We have it in your laptops when you when we tell you that your laptop has eight or 16 or 32 gigs of RAM. So random access memory is where the applications are open are executed while you are using them. So if you are running let's say Facebook for example or Instagram actually that is a program that will be executed when you open it in your devices random access memory and as long as you are using it before you shut it down or close it it's going to be in the RAM. Then we have the hard disk drives. This is where the storage is. When you switch off your phone and then you start it again, the images, the photos, the videos, and the contacts are still there. How come they were not in the RAM? When they are executed, they are in the RAM, but when they are in storage, when you shut it down, it's going to be in the hard drive. And that could be multiple types, SSDs or HDDs. And then we have how can we communicate to the outside world? Even if it is your phone, how are you getting on the internet from your phone? There has to be some transmission and reception device on your phone. So when we talk about servers and all that, we have what we call the neck cards or the network interface cards. And they could be Wi-Fi ones or they could be wired. A cable connects from here. So this is going to be inside your device, inside your server or laptop or computer or desktop. And then a cable will connect it to the network and that's how it communicates with the outside. or it could be wireless where it's just connected to a Wi-Fi network and so on. Then we have what we call GP GCPUs or graphics central processing units or GPUs and these are the ones that will do the heavy work when it comes to rendering videos or processing enhancing the processing time and so on. So think of them as additional CPUs that can do specialized functions and that will speed up what you do on your computer. So any computing device will have these components among other ones battery and plugs and all that. We are not but we are not interested in these for our discussion. All right. So I have a laptop and you have a desktop and you have an iPad. But what is a server? Why do we talk about servers when we talk about applications and the internet and the cloud and so on? Because your laptop despite it could be 2025 model but it's not powerful enough to serve a thousand or 10,000 or 100,000 users that would like to get into your e-commerce website and buy stuff from you. So hosting your e-commerce website on your laptop will not scale. And that's why we talk about servers and this is where we put the applications. Of course it could be rack mountable like the one that you see on the screen right now but they could be desktop servers as well. So with a box like a desktop computer, but the main difference between a laptop and a server is how powerful the server is, the muscles, how many CPUs, how many how much memory it has and so on. So server components are like any computing device. So it has as we mentioned it has a CPU, has a memory, it has a disk drive, whether it is HDD or SSD. It has network card or network cards and has GCPUs, but it's much more powerful. It has a lot of these quantities. It could have 16 tab of RAM, 64 tab of RAM, way more than what your laptop would have. The number of G CPUs, the number of GPUs, the number of disk drives, the number of network interfaces. So, you can think of it as a big muscle compute device. Basically, that's what the server is. And this is where Amazon.com and CNN.com and eBay and all the big top-notch and the big companies are hosting their applications and services. And of course, as your laptop, which is maybe a Mac or maybe it's a Windows one or a Linux one, it will have an operating system. The operating system is the one that uses the hardware, the RAM and the disk and the memory and so on. So that's the orchestrator on how these work. And that will be the mediator between your applications and tools and the hardware. So this is the translator or the brain at the end is the software. And of course it it depends on how you want to do it. You can have multiple applications on your server. So we have the operating system on top of which we can install tools and applications and so on. All right. So okay fine. I'm going to buy a server. I'm going to have that. But as the number of users increases, maybe that server is going to be really exhausted, overwhelmed to a point where it may slow down or just break apart. It cannot serve 1 million users who are trying to come because it has so much memory, but it has been exhausted. It has so much CPUs, but the users have been using them and the operating system is unable to handle that 2 million requests per minute that are coming in. So in that case we need to add more servers and that is called scaling servers. So in that case add two more, four more, five more, six more of course there is a process and a logic behind how many you would increase and that is physical servers but when it comes to the cloud they're going to be logical and autoscaling configuration. As the number of servers increases we cannot keep them under my desk in my office. I have to move them into a secure place. And this is where the talk about data centers started about 20 years ago. They used to call them server farms before. So data centers are massive locations, real estate location that is airond conditioned, secured, monitored and prepared. And as you can see in the picture, it has cabinets where this is one server for example in that. So this is a second server and so on. So each one of these is a server and then from the backside they're going to be cabled and connected to the network and this could be part of Facebook or Instagram or Google or one of the data centers one of the big data centers okay when the cloud started data centers are now becoming hosted by providers like AWS like Azure like GCP like Alibaba and so on but in essence a data center is a data center so number of racks there could be thousand of racks And they are built in rows in a very clean place that is air conditioned, monitored, powered, secured with surveillance with access control and so on to host the applications on servers. All right, so we have the server. We bought the most powerful one and we spent $200,000 on that P server platform and life is good. Now it can handle 2 million requests and then we needed more because our business is growing and we added more servers and so on. Now when you have one server and you start installing different applications let's say 3 4 5 10 20 we are just dumping applications on the servers and then we realized we started to have issues. Why? Because I have multiple applications written in Python but they need different versions of Python. Some of them are old, some of them are new and now they need different runtimes or maybe Java and they need different versions and runtimes. Similarly, we are running MySQL version 8 and MySQL version 5 and all dumped on the same server. Now, someone comes to troubleshoot a problem for application A and then looks at it say Python 3.8. No, that's wrong. Delete the file. Let's download Python 2.7 and that's the right one. Then that breaks another application that was using that file. So dependencies and versions and all that is an issue when you start dumping applications on the same server. One would say, okay, so why do we have more than one application? Why don't we have one application per server? Yep, that's easy. But the server is very costly and you would like to use or to utilize the resources within the server as much as you can. But doing so and putting more applications ended up being dependency issues and troubleshooting and errors and all that. So drawbacks include resource contention and inefficiency, dependency conflicts for different versions, lack of strong isolations, the admin of one application can see the files for the other application and he has or she has no clue about what that is and they start deleting and changing things. So you have security risks. If one application is compromised, everything else on the server is also compromised because of the lack of isolation and I want to scale app one because it's in high demand and all that. But app two and app three are okay. So what do we do? We add more servers and we only dedicate them to app one. How about the resource utilization on the additional servers? Because app two and app three, they don't need that. They have enough power on that one or two servers. So adding more that means it's going to be waste of money because the resources are going to be very well utilized and of course deployment and maintenance hell and add to that what if you want to move it to another data center I want to move that application we are now growing so we bought a new facility a new headquarter and we would like to move our stuff so now we need to move the physical servers not just take a backup and then move the backup on the other side so it becomes a painful thing with physical servers and that's why they said okay why don't we just go into virtualization which is the next step and of course lack of portability as I mentioned so that had led to a solution called virtualization why don't you split your physical server the one that has the biggest muscles on earth and split that into multiple virtual servers and you have this much disk space and you have this much RAM and you have this much CPU, why don't you virtually split that among the virtual servers and that will give you the isolation you were looking for. That will give you the best utilization for your server resources and that will also give you the portability if there is a way I can take a backup of each one of these virtual servers which is going to be much less than a physical server and then move it into the other location and scalability. Now put app one into a virtual machine, put app two in a different virtual machine and so on. So this is how it looks like. So in virtualization so as you can see here and here they are identical operating system they could be identical both are Windows or Mac or Linux but then we introduce an emulation layer on top of which we start creating what we call virtual machines. So we start to create the virtual machines or the virtual servers and we put app one in one server, app two in another, app three in another, database my SQL in a fourth one, database reddis in a fifth one and so on. So we did that. So the hypervisor would make each virtual machine feel that it has all the required disk, memory, GPU, CPU, network cards and so on that it needs for the operating system to function and for the applications to function. So this could be a virtual machine with a Linux let's say real Red Hat Enterprise Linux. This could be a Windows server and this could be a Linux Ubuntu based for example. So now we can have different operating systems. They are isolated from one another and I can deal with each one of them as a one app virtual machine. So now isolation and conflicts and dependencies and all that disappear and I have better portability. So this introduced us to the concept of virtualization which has been ongoing since 2003 2004 time. So virtualization allows us to run more than one virtual machine, multiple operating systems and application on a single physical server which is a good thing. They are isolated and we can take a backup of each virtual machine. But of course the backup is going to be a good size because it does have a full operating system. So full operating system plus the apps and so on. This is going to be in the tens of gigabytes in size. And a VM is going to be a set of files obviously. So what are the resources that the hypervisor facilitated access to for each virtual machine. So it will grant it or provide it with a vCPU, v memory, vesk and v network card, vgcpu and so on. So why do we say v? Because this is a virtual machine and this is not a physical. This is an allocation of the actual CPUs on the physical server. So that's why we call it vCPUs, vmemory or vramm and vesk and v neck and and so on. So each virtual machine will be given what it needs for its operating system. We call it the guest OS and the applications to be installed successfully and to perform successfully on the virtual machine. That's why we have the V-neck, we have the vesk, and we have the vramm and the vcpu for each virtual machine. What are popular hypervisor providers? We have VMware vSphere, we have Zen, we have Microsoft HyperV, and we have Linux KVM, we have Oracle VM Virtual Box, and we have VMware Workstation. Virtual machines despite they are much better than physical servers for the reasons we have mentioned but they have issues as well. So first one is they are heavyweight. Each one of them has a full operating system and the applications and so on. So they are slow to start. They could take minutes to start depending on how many apps and packages are installed. So limited scalability because the physical server has so much memory and so much discs and all that. So it I can go maybe to 5 10 15 60 virtual machines but then what I have to spin another physical server and so on and the problem with the reproducibility is an issue. So a developer is working on the app works perfect on his machine or virtual machine on the server but now ships the image to the testing team but the testing team when they are starting the application there is a lot of errors but then he would say oh but it works on my machine it's your problem there is something missing maybe dependencies maybe you have the wrong versions you need to make sure that everything is exactly like the long list I have boom go ahead and build the same machine or you know what come and take my physical server ship it to your location and work on it. Of course that's stupid to do. So the repro reducibility will be a problem with virtual machines and we have multiple operating system. Each virtual machine requires its own operating system. So let's say I have three virtual machines and they're all Windows but then I have I need the license for the first one, the second one and the third one. I need to install a complete Windows on each one of them. I need to start that. that I need to take the resources and the disk space and the memory for each one of them. So that's a waste of resources or inefficient use of resources. Image management, the virtual machine image management is not as easy especially because of the size and because of the lack of reproducibility perfection that we talked about and portability of course is going to be an issue based on what we have discussed. So what was the reason or what were the drivers of looking into containers if we had virtual machines. So this section is going to take us from the virtualization to containers and what was the background what was the reason that we moved or technology moved into containers. We still have virtual machines but the more popular are the one that is getting more attraction is the containerized the cloud native and the containerization docker kubernetes and all that. So before we delve into this let's find out or let's understand what is a Linux software process or what's a software process in general if we are talking about Linux or Microsoft Windows and so on. So the process in Linux terms is a running instance. So an execution of a program. So let's say for example engine X or um Tnet or Ping or anything any program. So any tool or any program that when it is executed it has its own memory. It has its own CPU resources and system resources but it is managed by the operating system kernel or the Linux kernel. So if I have Apache for example or engine X or Tomcat or whatever is the program that I'm running or maybe a calculator on Linux or Python and then I run it then it's going to be run as a separate process kind of isolated from what is around it. So when we run any program in Linux like bash, engine x, python, apache and all that. So what would the Linux kernel do? It will load the program code into memory. We're talking about RAM, the random access memory. It will allocate it a unique process ID or P P ID and it will create a process to execute the code. So these are the three things that will happen each time we run a program. So each time you run a program or a tool that you have in Linux, there will be a process generated based on that. Why did we mention that? Because containers when they run into Linux or or Windows, they run as lightweight isolated process that is in a shared operating system. As we will see throughout the lab that we're going to run all of that on Ubuntu Linux. So each time when you run a container, it's going to be a small size, lightweight, like a small size. It doesn't need a full operating system. We're going to get into that. And everything that container, let's say the container is for Apache or EngineX, anything that it needs in order to run in terms of code, libraries, environment variables, runtime, configuration files, they are all going to be within that process. So let's take a simple example. Python calculator written in Python. In order for Python to run, it needs to have the runtime. So basically the interpreter that will take the Python commands and tell the machine or tell the hardware and software what to do with it. So that with any tools or configuration files and with the code in Python itself and with any environment variables, usernames, passwords and so on, all will be encapsulated into what we call the lightweight isolated process which is the container. And this is why we brought into attention the Linux process or what is the Linux process? If you put that in a visual format, let's say that the container is this box um we we are just trying to visualize it. This is not we don't have boxes in operating systems. So the code in Python in my example, the runtime, the interpreter, the Python 3 that will run this and any configuration files required and any binaries or dependencies or libraries that are required. For example, if I'm running deep math, there is a lot of libraries I can load in Python that would help me with that. If I'm doing data analysis, machine learning, AI, data science, analytics, then there will be a lot of libraries I can load that will help me. All of that is going all together be put into the container and the container will be considered the program that when I run it will run in an isolated process. Think of shipping containers. So let's say the container on the top. If I shipped that container and I put all my furniture and my appliances and all that inside the container and it is closed. Now if I decide to send it to Latin America when I go there I'm going to find exactly the same. If I decide to move to Australia the same container then it will be shipped to Australia. When I travel to Australia I'll find exactly the same content inside that container. So that's exactly the concept of containers and it was derived or it was inspired by the shipping containers and of course we can run applications inside containers because the code we are talking about here will be more or less to do a specific program a specific function or to solve a problem or maybe be part of an application. the features of containers and the reason why we're getting into that because we are going to take a step back afterwards and contrast that to the issues or limitations we discussed with virtual machines. So the features in containers that they don't need a full operating system and we're going to explain how each one runs into a process that is isolated self-contained and it has everything that it needs. It is much faster because it doesn't have a full OS and it is lightweight. It's much faster to create, start, and tear down. It's repeatable. The same one, reproducible. Basically, the same container if you run it here or if you run it in Hawaii or if you run it on AWS or on premises, it's going to be the same thing, reproducible and definitely like shipping containers in shipping industry. It is portable and it's easily scalable, lightweight software process, then we can scale very easily. All right. So that's all great, but how can a container run without an operating system? That's what I mentioned. And there has to be a way to do it, right? In order to build, ship, and run containers, there has to be some magic that happens on the host. If it is a program software process, it has to be running on a computing device, on a server. So how can that happen? How can we run containers? Let's say this is container one and container two. How can we run this on this server that has an operating system? There has to be something that would allow the container to feel that it has an operating system. So it will lean on the operating system of the host. So basically they are going to share the kernel of the operating system be it Linux or Windows or Mac OS we don't care that operating system is going to serve all the containers. The kernel is going to serve all the containers that are in the same host and that emulation or that mediator is called the containerization engine or the container engine or if it is docker then it's the docker engine. So now we have the dotted line that represents a container. It has the application code configuration dependencies binaries libraries anything that it needs to run and it is a self-contained entity that will run as an isolated process. So without the container engine we cannot run containers and notice that we don't have a hypervisor here. We don't need the hypervisor. So now we are sharing or we are allowing the operating system to be served by the engine the container engine to serve all the containers and this is how the containers don't need their own operating system. Containerized applications as we mentioned they run into separate processes isolated and docker is the most popular container engine and it has been out for about I don't know 12 14 years now. Docker is available as a community edition which is free and it's also available as a paid edition which is enterprise edition or e. All right. So docker containers from the docker file to an application. How can we start a container? We looked at the previous slide that there was an existing container but where does it come from? How do I start it? How do I write or what do I need to do in order to configure a container and allow the operating system to find out that there is a container. So we start from what we call a docker file a script text that you write down. Of course it has syntax and there is some understanding and knowledge behind it. Once you have that docker file, then it will be used to create what we call a container image and the container image can be used to run containers across different environments. If you look at how this happens, we have the docker file and here's an example. It's a text file. Remember when we said one of the advantages of containerization is the fact you can do version control. At that time I mentioned that version control is possible because it is more or less text files. So from the docker file we need to create or build what we call an image. And as we will see shortly that there is a command called docker build. It can take up a docker file and build the image. So what's the image? That's the template from which you can create containers. Think about it like the virtual machine ISO file for example that from which you can build virtual machines. Now we can do a docker run command and then we end up with the running applications inside containers. And of course this is reusable. So the image can be used hundreds, thousands, tens of thousands, millions of times without any issues. Let's put them side by side and do a contrast. Virtual machines and containers. So on this side the hardware is exactly the same. The operate operating system could be the same. And then we have here the hypervisor. The purpose of the hypervisors was to emulate or let each each virtual machine. Let's say this is VM2 and this was VM1. So let's every virtual machine think that it has the right hardware that it needs. They were not leaning on the operating system because each one of them had its own operating system full operating system be it Windows, Mac or Linux or whatever. On this side we don't have the hypervisor the hypervisor but we have the container engine docker engine and then we have the containers running on top sharing the kernel or the operating system. So the way they share the kernel is through the docker engine. Now a question can we run containers on virtual machines? So here it's obvious that we can run it on physical servers. This is a physical server. There is no hypervisor. So that is absolutely a physical server. Now can I run it on a virtual machine? And the answer is absolutely you can. And if we put both together in one drawing it will be exactly like what we see now. So we have the hardware the operating system. This is the physical server and then I have the hypervisor which can create VM1 and VM2 in one of the virtual machines which has a full operating system. I'm going to install Docker engine a container engine and the container engine will allow containers to share the guest OS in this type. So they don't have anything to do with the external operating system on the physical server. And on top of that, as long as I have the Docker engine and I have the operating system, then I can run containers. That will be container one. Here I'm talking about the internal one and container 2 like the arrows show. So I have virtual machines. I can pick one of the virtual machines and make it a container host by installing the Docker engine or the container engine and then they can start working together. sideby-side the comparison or why the containers. How did we get the containers from virtual machines? Because we had the fact or the issue or the limitation that virtual machines are heavyweight, slow to start and that's why containers are lightweight and they start in milliseconds. Virtual machines have limited scalability because of the physical hosts limitations. Containers they have much faster scaling and they don't take much time and they don't take much space as well or resources. Virtual machines are low in portability because of the reproducibility limitations whereas containers are have excellent portability. Virtual machines I have one operating system in each one of them. So that's more resources consumed by the requirements of the operating system. Whereas in containers they share the operating system of the host. Here we have inefficient image management. Part of it is the size and the variations between the different environments. Whereas here it's efficient image management and we will find out later about docker hub and repositories where or registries where you can ship your built images and then they can be pulled for whatever reason in whichever location. This one has poor development tested production. Basically environment parity will be poor. Whereas in containers since they have everything within they are excellent for different environments and for CI/CD applications as well. So what are examples of the popular container engines and runtimes? We have Docker, of course, that is going to be the course. And then we have Linux containers, and these are more low-level containers that was before uh Docker, the LX, LXC or Linux containers. And there are system level containerization framework. Then we have containerd which is geared more towards Kubernetes. And then we have Creo, which also is geared towards Kubernetes deployments. Let's talk about Docker architecture. What are the components that make up what we call a Docker host at the end? What are the different software components that play within the container engine or docker engine in order to allow us to perform or to use Docker and create containers and tear them down and so on. So, Docker is a software platform. The Docker engine that we discussed is a software. It's not a hardware thing that simplifies creating or building, running, tearing down and while it is running managing the containers or applications in containers at a scale. It is developed by Docker Incorporation and it's an opensource software and it virtualizes as we mentioned or allows the sharing of the kernel the host operating system and the applications running in containers they will be running in isolated environments the processes that we discussed and Docker can be a community edition which is free anyone can play with and there is an enterprise edition that has additional features But you have to pay for that. So what are the components within a docker host that in order to be able to use it efficiently? Number one is the docker client. That's the interface. When you type anything any command that starts with the keyword docker, then that client is going to understand what you want and that is going to send in the request to the next component. So it enables developers, users to interact with Docker. That's the interface that you have. And we can run commands like docker pull, docker run, docker build. Don't worry about that. We're going to find about it later on. And we use command line interface to do this. So when we use the docker commands, what happens is the client is going to understand what you want. It will validate it and then it will send it to what we call the docker service or the docker demon or dockerd. We're going to talk about this next. The next component is the Docker host. That client, where does it exist? I need a host. I need either a virtual machine or a server in order to install the Docker engine. And then I will have the CLI. So that thing is called the host. The virtual machine or the server where the Docker engine is installed is called the host. And as we mentioned, it can be a physical machine, physical server or a virtual machine. Then we have the docker demon or the name is dockerd which is the heart of docker. That's the brain of docker. Then we have docker images. So we start with a docker file. We create the images and then we create the containers. So the images or the templates these are read only binary templates and we can use them to build containers and they are reusable. I can build 1 million containers from the same image and it's not going to vanish or expire or be depleted or anything. So the templates they define the application code where to get it or download it from any libraries required any dependencies any configuration files any environment variables they are all going to be in the image and obviously they must have been in the docker file which was transformed into an image and now we can run the application that this code is building inside containers. So inside the host we have the demon and then we have images. So we I can have multiple images on my host. Okay, let's zoom into the docker demon to find out that heart of docker. What exactly does it do? So the docker demon is going to wait for API requests coming from the client. We mentioned that the client as you type commands it will validate and then it will send in requests to the demon and then it will create containers and it will manage them. It will create images, networks and volumes. Okay. So the demon is going to be the heart of all this. Is it itself going to create that? Hold on. We're going to come to which component exact exactly within docker that is going to do the actual creation and management of containers. Also the docker demon will build container images as requested by the client. When you do the docker build command, it's going to build images from the docker files you are pointing to. And it interfaces with the docker registries. So it is the middleman between the client the registries and what happens on the host. So when it interfaces with the registries, it's either to publish, we have created an image, let's put it on the registry so people can benefit from that or to pull an image that doesn't exist but I need it. So as requested by the client, the docker demon will be able to do all of this and it will manage the life cycle of the containers from starting, stopping, deletion or removal. All of that is also managed by the demon. So if we have the image and we have the demon which are inside the docker host then we can start building containers. So containers are nothing more than encapsulated environment which you can use to run applications. A container runs as a process in an isolated environment. We know this it packages the container packages the application and its dependencies in a single executable unit. the program or the process that runs at the end. All right. So since we talked about the demon and the client and the host and we talked about the images and the containers then we need to also highlight the registries where we can host and store docker images. So if I have an image then I can if I create the image then I can ship it into the registry. So it will be safe. If my laptop crashes then it is in a safe place. I can provide the link or the URL for others to download that image and use it and it I can make it public. If it is something unique that it doesn't have to do with my corporate and I'm building and giving back to the community then it can be published as public and everyone can benefit from that. Dockerhub is the public registry that anyone can use. So that's the most famous registry that is available to date. when needed we can pull images to the host from the registry. So this is going to be within the host and then we can pull images if we need them. For example, this is a brand new host and I would like to start an Ubuntu container. So then I need an Ubuntu image or engine X or Apache or whatever. And users can also push their created images to the configured registry. So again I am pushing from the host out or I'm pulling into the host. So pushing and pulling images. We put all of that in one page so it becomes easier for us to deal with. Then we have the client. We have the host with the docker demon. We have the registry where we have all the images that we need if it was docker hub or it could be a private registry for the corporate. So we have all the images we need for the corporate. So most probably we have built them and now we are using them. So if I have a docker pull command issued by the client, the request will go to the demon. The demon will head to the registry. If it is not available on the host, then it will head to the registry to see if we can find it. Let's say for example I wanted docker pool. I wanted to get an Ubuntu and a Postgress uh database. Then the docker pool will bring in these images and they are going to be on my host download them on my host. Now since I have them then I want to start building the container. So I can do docker run and docker run will go through the demon again from the client and we'll use the images that we have downloaded to create uh an Ubuntu container and a Postgress container. And of course, if you have the Docker files, we can build our own images as well. So that is something also we can do. And the request will go to the demon. The demon will know which Docker file will pull it. And then we'll create an image. And then I can push the image into the registry. As you might have guessed it. All right, let's find out how Docker works inside the host. Remember when we said that the Docker demon is how it manages or is the entity that is supposed to manage create the images, push the images, deal with the registries, understand what's coming from the client and manage networks and containers and volumes and and so on within the host. So does it have any assistance? Let's find out. So understanding how do works inside the host. So the CLI will communicate with the docker demon or the docker server which is abbreviated dockerd. Then what would docker d do? Dockerd will process the api request coming from the client and it will utilize containerd functionality. So there is a component within the demon that is containerd to manage the container life cycle. Then it does containerd itself create and kill the containers. So the containerd will manage the containers will manage the storage and will manage the networking relevant to the containers and it pushes and pulls images. So the containerd will function within the demon in order to push pull m messages manage containers storage and networking. Then we have something called run C and that is like lower closer to the container which will create and run the containers. So now we have the CLI, we have dockerd, we have containerd and we have run c all together are going to be within the docker engine inside the host and these are the components that work together behind the scenes. I don't see that in order to make sure that our requests to build images are fulfilled. Our requests to push or pull images are fulfilled. Our requests to build containers, to stop them, to terminate them or to build volumes and storage or networking are all understood and they are fulfilled as well. So let's go ahead and set up the environment that we are going to use and we are going to do it in AWS. I know a lot of you are going to push back and say why not on my laptop I can't do this v virtual machine I can't do virtual box I can't do this I can't do that I have my reasons so let's discuss that first and then at the end it's up to you all I need is a virtual machine that will be the docker host and we're going to do all of our labs on that host now why AWS why do I prefer to do it in the cloud if you if you want to do it in Azure if you want to do it in GCP that's fine as My point is let's do it in the cloud. Let's do it in the environment where you are going to be interviewed and asked question about and also that when you defend the fact that maybe you don't have actual experience in docker or in cloud or in devops then you can at least say that I have created these projects in the cloud. So you know how to deal with the cloud. If they ask you about AWS or Azure or Google Cloud, then you know and you have dealt with it. It's not a black box for you. So let's go through why I think working in the cloud is way better than an isolated environment or a sandbox. First of all, you are practicing in real world environments. environments that you are going to see and touch when you work in your actual job after you get it. It's much faster and much cleaner to set up and delete. So let's say you bring up a virtual machine that will be your Docker host. Whatever happens and that virtual machine is trashed then you can in two minutes launch another one. You can build confidence, personal confidence, technical confidence in working remotely and collaboratively as well. In today's IT, you could be working with the team in your corporate, but they are in Japan for example and you are doing something for them in the cloud in Japan and you are in the US or you are in Europe. Then the confidence of working remotely and connecting to your infrastructure remotely and building that remotely is going to be gained as opposed to this is my Windows laptop. I'm going to do stack work stack overflow and find out how to do a VM but then the mouse doesn't work. I cannot copy. I cannot do this. I cannot do that. And we have lived through hell through other courses with other instructors in our academy about virtual box and the compatibility for the different and the resources and the M1 on Mac books and all that stuff and then you are going to master the glue between tools. when you do anything the cloud is going to be there in today's it in I would say 70 80% of the cases the cloud is going to be there some are on premises still so when that happens then you will be already using the cloud using the pipelines using other tools in the cloud and this is not new to you Linux operating system you are going to be practicing on Linux operating system all the way throughout the course and again you can defend send your project and your GitHub port uh port portfolio for the projects you have done when you are asked but yeah but you don't have practical experience then you can reply back and say yes but I have done that in the cloud and I have done that with real environment and these were not sandboxes or isolated or following a dumb script I have worked myself from scratch on my projects and I have done everything from the ground up and most importantly because this is why a lot of people they push back on any environments in the cloud is cost and it is free whatever we are going to do throughout this course. If you have a brand new AWS account, you will get the resources that we are going to use in this course for 12 months for free. And I'm going to tell you exactly what are the free tier services you are going to enjoy for 12 months without having to pay a penny to AWS as long as you don't cross the monthly limits that I will explain in a different video. All right, so hopefully that has convinced you to start doing this. All you need is a credit card. And in the next video, I'm going to tell you how to create the AWS account. What about if you cannot or you do not want to create an AWS account? You don't have a credit card. You don't want to use your credit card. You don't trust me. You think that they're going to charge you. You want to do it on your laptop because you just bought it and it's new and you're happy with it and you would like to get a return on investment on what you have just paid off. Whatever the reason is, there are alternatives. Although you will be missing on all of these points except for the Linux OS but other than that it's not going to be real world environment. It's not going to be fast to implement. You may run into issues and it doesn't have to do with real world environment. So it's up to you at the end. So what are the alternatives? The alternatives are Docker Desktop Personal and this works for for Windows, Mac and Linux. And if we click on this link, it's going to take us there. So you have the number one containerization software developers and terms and if you want to choose plan of course we are not going to pay for that because there is one that is free. The docker personal is free as you can see and you can get started and then you can follow fill in your information whether it is personal or workrelated. Fill in your profile or maybe login with GitHub or Google and then you will follow that to download it and install it on your machine. Let me know if you need any help with that. I can help you with that as well. Why I did not include a video for that? Because I am opposing that direction. But it's your freedom. Do whatever you want. Let me know if you need help and I can post a video about how to install it. So this was the first alternative. The second one is on your laptop. You can also do a VM, a virtual machine. So you have a Windows laptop or Mac or whatever, you can carve some of the hard drive and then you can download Oracle Virtual Box and you can start uh creating containers and this is from Oracle and this is where you get it from. So Oracle Virtual Box and then you can download based on which platform you're going to use it for. You can even do it on Ubuntu and other Linux distros as well. So, choose the one, download, follow the steps, and then you will install it. This one is a little bit tricky for the mouse and copying and all that, but definitely you can at the end get it done. Again, I'm not opposing, but I'm recommending don't waste your time on that. You need to learn Docker, not how to set up virtual boxes, which you are not going to do in real life. And it is free on on the cloud, on Azure, on AWS, on Google Cloud. Choose the cloud that you want. It's up to you. So what are the options we have? We have the virtual machine from VMware Workstation and that works on Windows and Linux. And again if you click on this you will go to the website where you can start downloading Fusion or Workstation depending on the platform that you're going to use. So this one is uh Fusion Pro for Mac and you have VMware Workstation Pro for PC. So choose depending on your device and you can follow the steps and install it again to your liking. But what I guarantee you in all of these cases is it's going to waste time. It's going to take time. Maybe if you are in it and you are proficient about about this maybe half an hour, 20 minutes, 1 hour and if you are not maybe it will take you days and it will stop you from proceeding with learning. So again I go back to the benefits of using it in the cloud for free. All right. Now since we are going to do most of our hands-on lab and practice in AWS in the cloud, we are going to work extensively in the cloud in this course and that will be a great opportunity for you to learn the cloud as well while you are learning the IT fundamentals. So what we'll do is we are going to create an AWS account free. Don't worry, you will not have to pay anything. And that will make it easier if you have an old laptop. If your laptop is busy or not performing, it's um full. The desk is full. You don't have to upgrade to another laptop. Just continue to use it in the cloud. That's it. So, what do we need to do? We need to go to aws.mazon.com. aws.mazon.com. And you will get a page like this one where you click on create account. So, we need to open an account. We have to have an account in order to use AWS services. So I'm going to click on create. And this is a free account from here. Get started for free. And this will tell you about the the options you have. You have a free plan. You have a paid plan. What's the difference between the two? The free plan is an account. It doesn't give you access to all AWS services. So there will be some services that you will not be able to use. and scaling of services is going to be capped. So when you are working and you are trying to scale and do like advanced stuff, it will not scale accordingly because there are some thresholds based on the credits. So these are the disadvantages and the account is going to be closed after 6 months from creation. You will receive $100 credits as soon as you open the account. So you can use AWS services worth $100 US. If you use them in one month, that's it. The account is unusable. You cannot add credits unless you change it, upgrade it into a paid plan. And there are some activities that if you do exploring some AWS services and if you do them within the six months, you will get another $100 credit. So you'll have $200 credit and that's a lot of money for someone who's learning AWS. I mean that could easily help you do a lot of AWS stuff that would take a year to to work on and you you'll have free usage of select services and there's no charges whatsoever. So if you are worried about incurring any charges that will be the account but of course you have limitations. You can always upgrade within the six months to the paid plan. And in the paid plan the same thing you get 100 credits and another 100 if you do the AWS services exploration includes free usage. You can scale and all that but you are going to be charged if you go beyond the thresholds. workloads can scale beyond credit thresholds because it's paid. You will pay for it and you have access to all AWS services. If you need to know more about the differences, there is a an FAQ. So these are services that are available in both and you can keep exploring which services and you can always click on show more and it will tell you if this is available in both or not and you will get an yeah this is the FAQs and in the FAQs they will tell you about so here the free plan accounts paid plan accounts earning additional credits what you need to do exactly and what are the activities that you need to do in order to explore that. How do I earn additional free credits? And you go through this console home walk through and dashboard and you can find out what needs to be done. So, you have everything you need and you can find it by yourself without having to ask me for any questions regarding these accounts. All right, let's go back to creating the account. You need to write an email that is going to be the communication between AWS and you for bills and for updates and so on and a nickname of your choice for the account. So once you have entered the email and the nickname click on verify email. So what they will do is they will send you a verification email to ensure that this email is an active email and you have access to it. And once you verify you will be taken to the next step. So once you enter the email and the name, you will get into this capture where you have to do the security verification. So go ahead and do it and then click on submit. Once you do the capture, enter a code that was sent to the email that you have specified. So you need to get that code from the email and enter it here and then click verify. And as you can see the email has been verified now. Now, now you need to configure the root user password. Basically, the username will be the email that you entered and this will be the password. And this is the most powerful user in your account. So, you have to be very careful and it's better to use a password phrase, not an easy to guess password. And the conditions are available here. It has to be at least eight eight letters uh long. at least three of and it includes three of the following uppercase lowerase numbers and non-alpha numeric characters. So go ahead create your password and confirm it and click on continue. You have the two options that we talked about the free and paid. It's up to you if you don't want to be charged under nor circumstances, but you're okay that you you will bump across some services that you are not going to be able to use. And of course, for this course, the free plan is more than enough. I would go with the free plan for now. Now, you need to select what will be the use of this account. So, I'm going to click on personal. Put all the details, your personal details. It has to be accurate. The phone number has to be accurate, the country and all that has to be accurate because they are going to send you a code to your phone and you will need to verify it. So now they have verified the email. They will need to verify the phone number as well. So fill this and after you do then takeick this box and click on agree and continue. Now you will need to enter credit card information. You might be wondering why is AWS asking me for a credit card if this is a free plan. Simply they need to verify your identity in three different ways. Email was one, phone was another. And now credit card information. That means they know you. they can verify and there is no way you can have wrong information entered here because they will check and probably they will hold like a dollar one euro or a small amount only hold they are not going to charge it and it will be released in a few days but this makes them sure that there is a payment method just in case in the account and if you upgrade to a paid plan then any extra charges are going to be charged to this credit card if you are on the free plan they will not charge you. So don't worry about that. But you have to enter this information. There is no way out of this. So fill this information and click on continue. And I will see you in the next page. Now is the sign up for AWS. You need to confirm your identity. And now they have given you an option. They can either call you and give you a code or you can receive a text message. So, both of them are used to verify that this phone is yours. So, go ahead, fill in the information and click on send SMS or you can have a voice call if they want to call you and give you the code. Either way, fill in the number, click on send, and then they will text you or they are going to call you depending on your choice. Go ahead, do this step and I'll see you in the next page. Now you are faced with another capture and then they will send you the verification or the verification code or the text message. So you have to fill this capture and then you will get the code. All right. So this is the page and you'll get the code. Enter it here and click on continue. Okay. So I got the code. It is 5320. 5320. Continue. Okay. In my case, because my um credit card, my phone number and all that exists already on AWS, they are refusing to give me a free plan and they will upgrade me to a paid plan. So, anyone who created an account before in the good free tier all times where we could create five 10 accounts and use free tier in all of them for 12 months, this is not the case anymore. you need to use a new credit card, a different phone number if you would like to get around and have another free tier. In your case, this shouldn't be a problem because if if you are a newbie to AWS, this page will not appear to you. So, in my case, I'm going to say okay, I agree. I'm not eligible for the free plan anymore. Anyways, I'm going to click on confirm because I want to show you the rest. So, that page will not appear in your case. Now, we come to the support plan. Leave it to the basic and click on complete signup. All right. So, I'm going to click on that and guess what? Congratulations. You have an AWS account right now. Click on go to AWS management console. All right. So once you log in that means you're going to the management console. This is the portal. This is the orchestration and automation and management tool in AWS. So I'm entering my account right now. All right. So, let me take you through a walkthrough of the AWS management console to help you get familiarized about the AWS management console, how to use it and all that. Let's go ahead. Okay. So, this is these are few messages. If you'd like to go through them, that's okay. For me, I'm not going to go through them. Let me make this a little bigger. So, this is the console home for a brand new account. So this is an account which doesn't have any recently visited services or anything. If you click on this side, you'll find the account ID. You can go to billing and cost management where you can look at your bills and find out your consumption and so on. You can sign out and here you can see that you have all the AWS regions. So by default it has chosen for me this as the default the one in Stockholm in Sweden but you can switch to a one closer to you because that will help you with the internet latency. If you want to play with an AWS service, work with an AWS service, then you can click on here and you can see that you have here a list of AWS services or if you know the service that you are going to work with. For example, in this course, we are going to work a lot with EC2. This is the service that allows you to create virtual machines in AWS, virtual servers in the cloud. Basically, if you would like to launch your own presence in AWS, you have to create what we call a VPC or virtual private cloud. There are some services under VPC that are created for you by default. You don't have to do anything about them and they are there for you. AWS assumes that this is like um common denominator that most of the people who are learning might need it and they volunteer and they create it for you. We're going to learn more about this later on. If you go into one of these services, I'm just going to show you how it looks like. You don't have to know anything about it right now. So, usually you have the dashboard. So, this tells you where exactly are you right now. So, I'm in the VPC dashboard, virtual private cloud dashboard. And these are the settings that I can choose or the stuff that are under the VPC. When you choose one of them, what you see on the right hand side will be the details of what you have selected. So for example if I click on this these are the subnets under subnet VPCs this is the existing VPC root tables these are the existing root tables. Now let's go to EC2 which is the virtual machines in the cloud and as you can see this is the service here is the EC2 dashboard as it says instances means virtual machines and instance types and launch templates and there's a lot of configuration stuff that also fall under the EC2 dashboard for example if I wanted to create a virtual machine and you will be amazed at how fast you can do that. So I click on instances. I don't have any as you can see, but I can choose to launch one. So this is the page that at the end when you fill in all the information, you can just click on launch instance and boom, you have a virtual machine in the cloud. So what do I need to do? I'm going to call it first VM, first virtual machine. And here you have the operating system. So you can do Amazon Linux, you can do Mac OS, Ubuntu Linux, Windows, Red Hat Linux, Suzi Linux and so on. So there are plenty of operating systems you can run on the virtual machine. Remember that the virtual machine needs a full guest OS and after that I will leave it to the default. So I'm assuming that I'm going to go with an Amazon Linux one. Any virtual machine has a v-neck, virtual memory, virtual desk, virtual CPU, and so on. So if you look here, you'll find that this is T T3.micro. That's the size of an instance or a virtual machine. And it comes prepackaged. So the T3 micro will always have two vCPUs, one gigabyte of memory, and here it tells you the prices per hour if you use it. So in my case, I'm going to choose let's see if I can get to a smaller one. That's fine. That's the least I can do. So T3.no keep pair. If you would like to access the instance remotely, then you have to create a key pair. Otherwise, I can do proceed without. We're going to explain that later on. Network settings, which VPC or where it's going to land. I'm going to leave everything to the default now because I'm just explaining that to you. Security and once you are done with all of this, all you can do is launch instance. And congratulations, this is your first virtual machine in the cloud. Successfully initiated launch of this instance. And if you click on that ID, you get to here and you will see that it is running and we have created a virtual machine. Of course, as you learn the the the particulars or the specifics about each one of the attributes that we needed to configure, then probably it will take you another 10 seconds, 15 seconds, but you will have a virtual machine in no time. You don't have to virtualize your laptop. You don't have to learn about new tools like Virtual Box or VMware Workstation. And you don't have to do nothing. Your laptop is asis. You don't need to split or partition it to include a a VM. You don't have to do nothing in the cloud. In your case, if you are new to AWS, it's going to be free. You have $100 credits and you can do some exercises and gain another $100 credits and it's going to be there for you for 6 months. You don't need anything else to do. All right? And at the end of the six months, as you advance, you can upgrade to the paid plan and then you start controlling your expenses based on your usage. Basically, you are investing in the environment that would look like the actual environment you are going to work on as you specialize in your career. All right, hopefully that was clear. What I need to do now is I'm going to terminate the instance because my account is not a free account. And once I click on that, guess what is happening right now? You'll find that it is shutting down and it will be terminated in no time. The second thing you need to do and it is recommended by AWS is I'm going to head to a service called IM identity and access management or manage access to AWS resources as they call it here and we need to click on users or I can go into IM and I would like to create a user that is going to be the one that we will use from now on in the account. Why? because it's recommended by AWS not to use the root account that you have used to create the account because that is the one that has the most privileges in your account. It's not recommended to use that one for the day-to-day stuff. So what I will do is I'm going to create a user. I'm going to call that user let's say admin labs or or can can be just admin and I would like to provide access to the AWS management console. So we're going to go ahead and do this and I'm going to create an IM user as we mentioned and I'm going to create a custom password for that user. Okay, you can click on show password if you'd like to view it. I don't want to share that with you. Next, do you want to add the user to the permission or attach policies directly? This is not recommended. It will work, but since this is not an AWS course, let's not get into a lot of details. So, administrator access, this is the highest privileges you can pro provide to any user. So, I have looked for administrative and this is the administrative access. Tick the box next to it and then click on next. This is the permissions that you are going to provide to the user and create user. So from this point onwards, this is what I'm going to use. Now if you want the credentials to be maintained, all you need to do is you can download the CSV file. It will have the this is the URL that the user needs to use all the time in order to log into the account. And this is the password. The only time you will be able to view this password is right now. So you better download the CSV file. And this is the user. So I'm going to use this in order to get into the account. And you will notice here that the name has changed. So I'm going to copy this and I'm going to download the CSV file. Please save it in a place where you know that is handy for your case. I saved it just in the downloads. I can relocate it later on. And then now I can return to the users list. I can email that to myself if I would like to. So I can email it to marketing dolphinate.com and I'm going to log out and try to login with the user and see what happens. So I'm going to sign out and here I'm going to use the URL. As you can see this is the sign-in URL that we have copied and I'm going to hit enter now. So if you notice now it has from the sign-in URL it had find found out what is the account ID. So all I need to enter now is the user and the password. And now I'm Oh I think I wrote something wrong. I think I misspelled the password. But I checked the CSV file and I found it. In your first signup, you will be prompted to change the password. So basically, the one that you have created with the user is a one time and you have to change it and that's a protection. Once you change it, you are going to use that one from that this time onwards without having to change until it expires. And by default, I don't believe there is an expiry, but if there is, it will be like 90 days or something. So you have ample time to use it without any issues. So, let's go ahead and change the password. So now you will see the difference here on this side that it's not the course labs anymore. It's admin at the account ID. All right. So since we understand how to work on the AWS account briefly right now then let's take it to the next step. Let's go ahead and launch an AWS EC2 instance an Ubuntu Linux instance. This is going to be the Docker host that we are going to use. So this virtual machine or EC2 instance is going to be what we will install the Docker engine on. And this is what we're going to use for practicing throughout the course. Why Ubuntu? Why Ubuntu Linux? Why not Red Hat Enterprise Linux? Why not um AWS Linux? Why not other dist of Linux? Because Ubuntu is not going to cost you anything on AWS and most probably you can do it in any other environment and it's available. So it's not a licensed product that will cost you a lot of money and that's why we're going to go with that one. If you work on Azure, if you work on Google, if you work on premises or on your laptop, you will be able to find the Ubuntu image and you will not find complications or cost associated with that. So what do we need to achieve in this hands-on lab? So here is what we need to do. We need to get to the AWS console and then we are going to launch the virtual machine or the EC2 instance with an Ubuntu operating system, Linux operating system and we are going to make sure that it is the free tier and we're not going to pay anything for that. In any virtual machine in AWS, there is something called a security group, a virtual firewall that protects the instance and allows which traffic comes from the outside and which traffic is allowed to go outbound or basically from the instance outside. So for that we're going to configure the security group to allow everything for now. We this is not an AWS lesson. This is not a cyber security lesson and this is not a production environment. So we by default all the traffic from the instance going out by default is allowed on any security group and we are going to allow all the traffic coming into the instance at the beginning. So that's what we are going to do and we'll configure something called an IM RO and I'm going to show you how to do that. All right. So that's all what we need to do and we are going and we're going to jump straight in into the AWS console and start working on this. All right. So here I am in the AWS console. So what do I need to do now? I need to go into IM before we leave. So this is the identity and access management. If you don't know how we got here, just type AM and then you'll have manage access to AWS accounts. AM. Click on that and then you will get to this dashboard. Before I move any step anywhere, I'm going to go ahead and do ROS. So in the left dashboard, create on rolls. Okay, I'm going to explain briefly what that is. We're going to click on create a role for an AWS service and we're going to choose from here EC2. And then I'm going to scroll down, click next. Then in the permissions, I'm going to click SSM. And you'll find an Amazon ECT ro for SSM. So I'm going to pick on that and then click next. And I'm going to call this AM RO docker. Okay. So I'm going to remember the name because we need to locate it. And then I'm going to go down and click on create RO. Right. And now if I look here, I'll find the RO is right here. And if I click on it, I'll find that we have the permissions of Amazon EC2 RO. Let me explain to you what that is in AWS. So let's say this big box right here is AWS. All right. So that's everything, the EC2 instance and all that we're going to do is within AWS. And this is where the internet is. And this is where the different users or even my laptop that I'm using right now, it's connected to the internet somewhere. All right. So what does the IM role do? One of the methods that I would like to access the instance in order to install Docker and do all the labs is called SSM, systems manager. So what does that one do? This is a service that sits within the AWS cloud somewhere SSM and any EC2 instance with an image from AWS will have an SSM agent a software that is installed in the AMI in the Amazon machine image in the operating system basically of the instance. So the recent ones, the recent instance, the recent versions will have that agent installed. As soon as the agent is installed and you bring up the virtual machine, then it will try if it has an IM role with permissions to communicate with SSM, then it will establish a connection with SSM. All right. So what is the point of having that? The point is this is like a pipe that is connected between them. a session that is communication channel open and through that communication channel one of the ways is I can use SSM to connect and get to the prompt of the virtual machine and then I can install Docker and do all the labs. We're going to see that next. So without the IM ro this cannot happen. So we need IM RO and we are going to use it when we are creating the virtual machine. Okay. So now we have fulfilled the prerequisites. I have the AWS account and I have the IM RO. Now let's move on to creating the Ubuntu virtual machine. Let's go back to the console. In order to create the virtual machine, I have to go to a service called EC2, Elastic Compute Cloud. This is the service through which we can configure virtual machines in the AWS cloud. I'm going to click on EC2. So now I'm in the EC2 dashboard as you can see on the left hand side Amazon Elastic Compute Cloud and I'm going to click on launch instance. But one thing before we move into this depending on your location choose an AWS region that is close to you. How can I do that? As you can see here, I am now if I launch a virtual machine, I'm going to to have it in Stockholm in Sweden. But then if you click on that pull down menu, then you have if you are in the United States, you have North Virginia, you have Ohio, you have North California, and you have Oregon. So if you are on the east coast, choose one of these. If you are on the west coast, choose one of these. In case of if you are in the US, go with North Virginia. But for EC2, I mean, nobody cares. Any one of them would satisfy that. If you are in Asia-Pacific, choose one that is close to you. So you have Tokyo, Sydney, Singapore, Seol, Osaka, and Mumbai. Right? If you are in North America, still in Canada, then you can go with this one. If you are in Europe, choose the one that is close to you. So this is Stockholm, the closest right now. And then you have South America, S. Paulo. So these are part of the regions. What if you are looking for a different region? Let's say Bahrain or uh Dubai or South Africa. Then you can go ahead and manage the regions and choose which region you want to work with. So in my case, I'm going to leave it to the default because it found out and this is the closest to me. Or maybe I will go with Frankfurt. I am in United Arab Emirates right now. So Europe is close to me. If I was in the US then depending when I used to live in California then west coast will make more sense. North Virginia anybody can choose North Virginia without any issues. The reason for North Virginia is all the AWS services are first launched in North Virginia and then they they are rolled out into other regions in the world. Now you need to choose which region that you are going to be working on consistently. What's the reason for that? Let's say I go ahead and choose North Virginia. I create my instance and then next time I log in without noticing maybe I would go based on my location I would go to the nearest region. So that could be Stockholm or it could be Sydney in Australia. If that's the case, then you're going to create that thinking. This was in North Virginia, but then when you move back to the US or when you go intentionally to the US, you start forgetting about resources you have created in regions that you don't use regularly. That's why please try to fix a region and always check that this is your default region and this is where you are going to create your resources. I get a lot of questions about I created the VPC and I did the subnets and I did this and I did that and I created instance but I can't find them. Yeah, because you switched the region and if you switch the region you can't see the resources in the other region. So for now let's go ahead and I'm going to create this in Europe and I'm going to choose let's say Frankfurt. That's the one I'm going to go with and this is the one that I'm going to stick with. What's the reason of choosing Frankfurt? Why geographical proximity is important? Because you are communicating with that region through internet links, right? So chances are if you are far away, if you are in Australia and trying to get to the US, then it's going to take longer and at times it becomes really boring that you click and then you keep waiting and waiting for the page to load. So choose one that is close to you and stick to it at least for now. So now I'm in Frankfurt and I'm going to go ahead and create a virtual machine. Launch instance means create a virtual machine. And here I'm going to name it Docker host. So I will choose the name Docker host. It's up to you. You want to call it George, you want to call it John, Samantha, it's up to you. Choose a name that makes sense to you and you like to use it. Then I'm going to go down. And now it's time to choose the Amazon machine image. The operating system and it could have also some other components defaults to Amazon Linux. And I'm going to go ahead and choose Ubuntu Linux in this case. And as you can see here, then I'm going to go with 2404. That's the version of Ubuntu. I don't want that. And I'm going to create only one instance. So there are no worries so far. So that's the AMI. Okay. Right. Then the instance size and it's T2 micro and as you can see here that it has let me just zoom in a little bit T2 micro. So it has one vCPU 1 GBTE of memory and that's what it has. As you can see here there will be a charge which is like 1.5 cent or something or.5 cent per per hour taken from your credit key pair name. If you want to connect remotely to the instance, there could be a chance that you need what we call a secure shell, an SSH, an encrypted connection between you and the between your laptop and the virtual machine or the EC2 instance. So for this, I'm going to create a new key pair and I'm going to choose it. I'm going to call it Docker key. I think I mistyped that. Docker key. And I'm going to leave this to the default. I'm going to create the key here. Notice what will happen now. So, as you can see, it's automatically going to be downloaded to my machine. If it is a Windows machine, this is a Mac OS machine. If there's a Windows machine, you'll find that it is downloading somewhere in here. It is very important to know which path, which folder it's going to go to on your laptop because you will need it or you may need it depending on how you will connect to the machine. So please when you see that then you can right click if you if it is a Windows laptop right click and find out the properties and the path where exactly it was. Did it go into C downloads or into a specific folder? I'm going to show you that in a different video so don't worry about that. Now we are talking about my machine is a Mac OS. So that that shouldn't be a problem. So I know that it is in downloads folder. I'm going to save it. So now it has been downloaded into my downloads folder. All right. Next step. If this is a brand new account like mine, then don't worry about going into here because they are going to be all the same. So this is where the virtual machine it will exist. And then for the subnet I can just pick anyone because they are all the same and they are all connected to the internet and we call them public subnets. So if this is if you are new to AWS just choose any one of them or just ignore it. Auto assign public IP please don't change this. This is very important because we need an internet IP to be connected to the virtual machine otherwise you will not be able to connect to it from the outside. Then here is the virtual firewall that I told you about here. Let me wipe this out. All right. So the virtual firewall around the instance that we needed to allow all traffic is what I am at right now. So I'm going to create a security group and then I'm going to call it docker SG and what I will allow is I will allow all traffic in the inbound direction from anywhere. So anywhere from the internet is going to be able to communicate with this virtual machine basically as if I'm disabling the virtual firewall. That's what I'm trying to do now. Right. And as you can see here, the storage for the virtual machine is 8 GB. And I'm going I'm not going to change that because I have a free tier. So here is another reminder about the free tier and what you have and what you can use per month. All right. One important thing to note here. What if I went on and I I said, "Okay, fine. You know what? I want the T3 micro, not the T2 micro." So, I'm going to scroll down the T3 micro here because we have the T2 micro available. As you can see here, there is no free tier eligible. So, if you decided to go with this one, which will give you two vCPUs and 1 GB of memory, immediately you will start being charged this amount per hour. So, don't do this. If you couldn't find T2 micro in that region, you will find that the T3 micro is going to be free tier eligible in that case. All right? So please be wary of that. If you choose any other one, as you can see, there is no free tier eligible. So these are all chargeable from day one. So please do not do these mistakes. Silly mistakes, but they could cost you money. All right. So now I have done all of this and all I need right now is to go ahead and launch the virtual machine. Okay. Now let me I could have assigned the IM ro while I was creating the the instance but in my case what I will do is I'm going to go ahead and you will see that there is a virtual machine right here and here is the ID and it is running and it's going through some checks initializing right now. One might think okay but how did you get here? I clicked on the link that appeared. If you didn't know how to get here, all you need to do is just to type EC2, go back to the dashboard which is here and then click on instances and then you will find the running one right here and this is the one that you need to select. All right, you will see here that it has a public IP address. So this is the IP address on the instance that is facing the internet. So if you are on the internet, so this is AWS and this this is the internet. If I would like from my laptop to get access to the instance, what do I do? Then I need to use the public IP address of the instance and type it on my laptop and then do whatever I would like to do with the instance. So that would be how you can communicate. So because when we are doing testing throughout the labs, I'm going to tell you go get the public IPv4 address of the instance and use it in your browser to do such and such. If I ever say that or if you you find this statement in any of the lab scripts, then that means I'm referring to this IP address right here. So you need to go to the instance to the docker host. If I mention docker host from now on, I mean the EC2 instance, the virtual machine that we have created with an Ubuntu Linux with a public IP address. So this is the public IP address. But what is this? This is the private IP address. When you log into the instance, you will see this on the instance and we're going to see that later on. Okay. So public IPv4, private IPv4. All right. Now I need to attach the IM ro to the instance to be able to communicate with SSM. So what I will do is I'm going to go into actions security and then modify IM RO and let me zoom out and I'm going to choose the docker im update. this. All right. So, congratulations. Now you have a running Docker host that has passed all the checks. Everything is running and all all good. What about if I wanted to add on the IM RO while I was creating the instance? It's very simple. You do all the steps that we have done, but then you go all the way down. When you have done all of this, you go all the way down and in advanced details, all you need to do is when you talk about the instance profile, you scroll down and then you choose this and that's it. And then you go scroll to the right and launch the instance. So all the steps that we have done, but when you get here, this is usually collapsed. You need last line you need to click on the triangle and then on the instance profile you need to choose the one that you have created beforehand and choose it and then go ahead and do launch instance but you have to do all the steps that we have done here and that will be the only extra step that you need to do. All right so I'm going to cancel this because I don't need to create a second one. Let me close this tab as well. So now I have my instance right here and I can click on instances. I can click on here and here is my instance. All right. Now if you have done it the way I have done it then there is a chance the agent might not have connected with SSM. So all you need to do at that case is you do a reboot for the instance. Reboot and it will be few seconds and the instance will be rebooted. Life is good. You finished the lab for the day. So you have worked so hard today and you would like to stop the instance so you don't consume from the 750 hours. What do you do? All you need to do is tick choose the instance state stop the instance. So if you stop the instance and then click on stop, you'll find here that the instance is changing into stopping. Takes a little bit half half a minute 1 minute and then it will be in a stopped state. I need to make sure that it has stopped before I leave. Keep refreshing the page until you see that it has stopped. But it takes time as I mentioned. You would like to zoom in. You'd like to minimize or maximize this. So you have to pull it from here. So now I can resize this if I wanted to. But of course there is a limit for how much resize you can do. All right. So I want to restart it again. All you need to do is come here and click on start the instance. all the time you have to take the instance first because if you have multiple ones you have to tell AWS which one you want to start or stop or reboot and so on. All right, let's now use SSM the one for which we have created the IM role and attached it to the instance. Let's use it to connect to the Ubuntu EC2 instance. Let's go ahead and find out how we can do this. Right. So here is my instance. If in your case it was not ticked, all you need to do is to tick the instance and then I'm going to go into instance state because now it is stopped. We have stopped this before we finished the previous video. And I'm going to click on start the instance and it wouldn't take long and goes into pending and then almost immediately after it will go into running. But this is still initializing. So it's not 100% ready. However, I'm going to show you how to connect. Let me click on this so we can widen the page without the navigation bar. Without the navigation bar and I can always go back if I wanted and I can open it again. All right. So now I have my EC2 instance. I have selected it and it's initializing. Refresh to find out where we are right now. We don't have to wait for that. Okay. So I want to connect to the virtual machine. Why do you want to connect to it? Because that is going to be our Docker host. We need to get to the prompt of the Ubuntu Linux and then we can start playing and down downloading the Docker engine and so on. So after ticking the box all you need to do is click on connect. Then as you can see here I have options to connect. I have the EC2 instance connect. This is based on SSH into the instance. I have session manager and I have SSH client. These are the ones we are interested in. So I'm going to start now with SSM. Session manager is a subservice under SSM or systems manager. So I clicked on connect. Now I'm going to click on this tab. So you have to see that this tab is the selected one, not this one and not this one. After you click on this, all you need to do this has to be in this orange color. If it's not in an orange color and it's in a gray color and you have some errors here or telling you that agent is not connected, maybe you did not attach the IM ro into the instance. So please go back and do this. How can you do it? As I showed you as we did it in the video, I'm going to go back to the instance. I'm going to click on actions then security modify IM RO and that's how you get into it. So that's what you need to do. In my case, I have done it. What's the proof that I have done it? Because as soon as I go into sessions manager, this is connect. The connect button is in the orange state. All I need to do is click on that and you will see that a new tab is now opening. And guess what will happen now? A new terminal is being connected. And as you can see on the left hand side, you are now at the prompt of the Linux instance. So if I do sudo su changing my privileges into the root privilege the highest privilege on the Linux machine. Click enter and you can see that I am now at the root and then some folder here. If I click on if I do who am I which is a Linux command it will tell you that you are the root you are the top. So what I need to do now is just do a cd forward slash hit enter and now I am at the root and this is the IP address the private IP address of the instance. How can I prove it? 172.31.42.177. If I go back here and let me just zoom out a little bit. 172 here is the private IPv4 address of the instance that we are in. And this is the Docker host instance that we created. You'll find that the private IPv4 address is 1723142.177, which means that I am connected actually to this instance. If I want to make sure that the instance is connected to the internet, what do I do? All you need to do is do ping. Ping is basically sending messages to an IP address on the internet and finding out if it is alive or not. So 8.8.8 8.8 that's the Google DNS servers that are available on the internet. So if you do this and then I'm getting a response without errors. So this is a response from this IP address. So basically the ping what it does is I'm sending you a message are you alive? And then you respond back to me if you get the my message and say thumbs up. I'm okay. So now Google is telling us that I'm okay. What does this signify? It signifies that your instance now or your virtual machine the Ubuntu virtual machine is connected to the internet. So it can communicate with the internet. All right. So now from the virtual machine to the internet all clear. Later on we're going to test from the internet to the machine but that is not what we need to do now. I will do a control C to stop the command. And now we have successfully connected into our virtual machine using sessions manager using SSM. This is what I'm suggesting to be the easiest way ever. So you don't need to worry about anything else. You don't need to worry about downloading stuff on your laptop. Nothing at all you need to do. So that's the way or the the first way to do this. All right. So let me show you a different way you can do it. And now it's not going to be through SSM. It's going to be through SSH, but again from the console. So let me go back to the console now here on this tab and I'm going to click on connect once again. All right. Now I'm not going to use SSM. I'm going to use EC2 instance connecting from the console through SSH into the instance. So I'm going to click on this and public IPv4 address is such and such. If you followed exactly what I have done, this should work for you as well. And the username is going to be Ubuntu, right? So if I click on connect, see what's happening now. A completely different terminal is opening. And it is not the SSM SSM is still available. If you want to check if I do the ping again 8.8.8.8 you'll see that it's still working. So this session is still working. I'll leave it open now and working. And here you'll find that we have a completely different one. So now I have through SSH I'm connected to the instance as well. How do I know? If you can see here, this is the Ubuntu user and it's connected at this IP address. If I just zoom in a little bit so you can see it. So now we have the Ubuntu user connected into this. And if you look at this, it's exactly the same 1723142.17, which is exactly the same here. If I do Ctrl C to stop it again, 1723142 177. I can do a clear And it's exactly the same. So I'm connected to the same virtual machine, two sessions and it's exactly the same. You will find out throughout the lab that I will ask you at times in the lab scripts open a new terminal session to the docker host. So what I mean is you have one that is open and you are connected to the docker host. Please open a different one. So how can you do that? All what you need to do is go here and click on connect and open a new session. It's up to you if you want to do them both SSM, if you want to do them both with EC2 instance connect or a third way that I'm going to show you as well. Different ways. All I need is yet you are at the prompt and you can type commands. That's all I need from you. Okay. But if you do here, if I do exit, this is the SSM1. Okay. So if I go here and I do a who am I and basically I'm telling Linux I'm telling Ubuntu which user I'm I'm using on the machine right now and this is SSM user. So anytime if you are lost and you don't know which terminal and and where did you get here and all that just do a who am I if you did the sudo su to elevate your permissions and then you can do all the commands on the machine you'll find that if you do who am I let me do the cd forward slash if you do a who am I here you'll find that now you are becoming the root so the sudo su changes you from a normal user to the root the top user in the machine basically here as you can see when I did a who am I it's a completely different answer who am I then now it's telling you you are the user Ubuntu but if I do a sudu su and I do a who am I again you'll find that you are the root so now I am 100% the same on this terminal and on this terminal all right so these are the easiest two ways that you can do in order to get to the instance from the console. You don't need to worry about what is your machine. Is it Mac OS? Is it Linux? Is it Windows? Nobody cares. Do you have to install any devices or anything on the machine? Nobody cares. I haven't done any commands. I haven't even touched which SSH key that we have downloaded. So the SSH key that we have downloaded is going to be if you want to access from your laptop remotely into the machine. These two methods are connecting from within the AWS console into your machines. So what if I'm done and I'm I'm done for the day and I don't want to continue. What do I do? So all you need to do is just close the tab and in the SSM terminate terminate or even if you didn't do any of that you just go ahead to the instance instance state stop the instance and you are done. Colossus I'm done for the day. So now I I can go back to the instances and then I check here and I'll find that it is stopping. If you do this and you are always stopping the instance after you are done, guess what? Now you are not going to be charged. Even the 750 hours are not counting. They stopped. What you are going to be charged for is the commulative storage for all the instances you are using if it goes beyond 30 GB. Now for this instance the storage allocated is 8 GB. So I can have a second one and a third one all in stopped states without any problems. I have the fourth one then the total is going to be 32. So I'm not going to pay for the first 30 but the second two I'm going to pay for at the end of the month. But don't worry we have the cost budget. It's going to let you know that this is what is the situation. All right. So this is how we can do it from the console and that should be more than enough. If you are happy with either one of these, stick to it and finish. We don't want to do any laptop problems. So finally it's time for us to install Docker on the Ubuntu EC2 instance that we have already created. So let's head to the AWS console to do this. So here I am in the AWS console. I have stopped it earlier because we were not using it while I was doing the other labs. Now it's time to tick on the box and then change the instance state into start instance and shortly as you can see that now it is in the pending it will go into running and then the checks are going to be happening for initialization. So what do I need to do? You have a lot of choices on how you can get into the instance. I'm going to use the SSM1 because I'm already in the console. It's up to you if you want to use mobile exterm your Windows SSH open SSH as we have shown in the video. If you are on Mac or Linux, you can do SSH through the terminal in Mac. You can do it directly uh from Linux. However you like. The point is we would like to be logged into the instance or the virtual machine and I would like to be at the command prompt because this is where we are going to do everything. So let's go ahead and click on connect. if you are going to follow what I'm doing. Session manager in my case and I'm going to wait until this one turns orange and then I'm going to connect. Okay, here we go. So, I can go from here and I have also taught you how you can go from here. Either one is fine. Choose whichever you like. So, let me do it this time through EC2 connect. The result is 100% the same. I want to be at the prompt. That's all I care about. So, here is the information that we have. The public IP, the private IP, and the name of the instance. And I am now at the prompt as you can see. All right. So, let's clear. If you are on Windows, on the command prompt, you'll do cls instead of clear. CLS, one word. All right. So, what do we need to do? In the code files, you will find this. And also in the PowerPoint you will find this link. So this is where we want to go and that's exactly where I got the VS code and the steps. So we're going to follow these steps. Here is the link. You can just copy and paste the link. What if you are looking at the instructions that you have in this file in VS Code and you found that it was different or some error go to the link. The most updated one will be to the link. If you send me a message saying that there is something wrong with the script or the the commands or I'm getting an error, I will go to the link, find the updated one. I will send it to you. So, you can use the link. It will have the updated information. Let's go to the link, visit it before we use this file. So, I'm going to click here on the link and it will take me to manuals on docker.com. So, I got redirected to docker.com under engine installation Ubuntu. All right. So this is for Ubuntu. Please be clear. If I go back to anyone, I have here CentOS, Debian, Fedora and so on to install it on these machines. So in my case, I am have an Ubuntu machine and I mentioned that the reason for Ubuntu is because of its popularity. It is open source and you can use it on your laptop. You can use it in Azure, in Google or in AWS or wherever you want. So this is the in installation docker in Ubuntu and we have the 2404 I believe the one that we have installed and some instructions and then it will start right here installation methods there are multiple installation methods and this is the many one and there is a convenience script but this is for testing and development environment this is manual step by step so we are going to take the steps from here And that's what is in the AML file. We are going to update the Ubuntu operating system. First thing, we're going to install prerequisite packages that will allow apt to utilize HTTPS. Update the GPG key for official Docker repo. We are going to add the repo to the apt resources and we will update the database with the Docker packages. And then we are going to install the docker packages container ID docker uh commercial edition docker compose plug-in buildex plugin and then we're going to check the status start it and we're going to validate the status again to make sure that it has been started enable it so every time when we stop and start the instance it's going to be active and then we'll do the hello world and then we're going to do some other commands. All right. So, let's do this step by step. I'm going to remove it from here, but I will be copying and pasting from this script which will be available to you. So, let's go back to the terminal and I'm going to start with the first one which is the update. Of course, you can try to do this. Could not open LO file and you have no permissions basically. So, why I have no permissions? Who am I? you are Ubuntu user. Looks like we don't have permissions. So one of the two two things either we do the command the same command with a sudo so we have higher permissions to implement it. That's one thing we can do. Lots of updates. All right. So we are done. Clear. The other option I have is to do sudo su. So now I have changed from an Ubuntu user to a root user. So I have all the permissions. I don't need to type sudo before every command as we go. Okay. Now we are going to install the prerequisite packages. Right. And I'm going to do the installation of the key rings. Then we'll add the GPG file. So now I'm going to start typing without the sudo and see what happens. As you can see it's the same now whether I use sudo or not because I have the permissions as the root mod the permissions and then we are going to add the repo I don't think I have copied the whole command all right then we'll do updates from the added repo Then we're going, let me clear again. We're going to install the Docker commercial edition containerdio. Yes, please continue. As you can see, some of the familiar stuff started showing up. Docker compose. We're going to look at it at the end. Dockerd build x. There are few packages that I have forgot. So I going to repeat the command but of course it will install only the ones that we did not go through. Do a clear again. Now Docker is now installed. So I'm going to check the status of docker system ctl status docker not long commands. So I have docker active started as you can see docker.service service and it's active and running which is good in your case if you found that it was not running what you can do is you can I did control C to get to exit um in your case you can do the command system start systemctl start docker if it was not running in my case it's pointless because it's already running and you have all that again in the script so you don't need to worry about that all All right. So, let's do system enable docker. Systemct ctl enable docker. So, every time we stop the instance, we start it again. You don't have to go and do systemctl start docker. So, you don't have to do that manual anymore. Now, it's going to be after every reboot. It's going to start by itself. All right. So, how can we check if docker is running? We can do this command. Docker run hello world. So now what we're doing is we are using a docker command the first docker command and we are building a container from an image called hello world. Don't worry we are going to learn all that together. So this is supposed to type if it works it's going to echo hello world. See what happened now. See the sequence of events I did docker hello world. Then it searched locally for an image called hello world the latest version. It couldn't find it because it couldn't find and unable to find it will pull it from docker hub. We're going to go through all these details. I'm just explaining very quickly. Pull completed. So it downloaded that image and then download newer image for hello world latest and then hello from docker. And now it's telling me that the Docker client contacted the Docker demon. This is what happened. The Docker demon pulled the Hello World image from Docker Hub. The Docker demon created a new container from that image which runs the executable and then the Docker demon streamed that output to the Docker client which sent it to your terminal. Try to do something more ambitious. You can run Ubuntu containers with such and such. And this is the hub.docker.com. And now if you run the same command again, you will find the hello from docker echoed here. So I ran a container and that container has implemented the hello from docker. Got me all these messages which proves that docker is running in my machine. So if I want to find out let me clear the version of docker that I'm running here I can do docker version as we can see here I have the community edition the version of docker is 28.1.1 and again the information repeated I have the containerd installed and this is the version for the containerd I have the run c which is the actual component that takes care of the containers. I have the version installed. All right. And we can also do docker minus v if I want the short form. It will tell me that this is what you have. So docker version is going to give me more details. And I can do docker info as well which will give me even more details about this. So let's see what we got from the docker info. So here is the command docker engine plugins build x compose docker compose and the version of docker compose and this is the server the server that contains the demon. So containers it's telling me that I have two containers right now stopped are two and image is one. So this is the hello world and these are the containers I created when I did the docker run hello world twice and as soon as it give me the output it went into exited state or stopped state we're going to talk about this in details and then we have swarm is inactive as you can see run C version container D version and the details of the machine I'm running on. So the architecture, it's a Linux machine. It's an Ubuntu. And here's the Ubuntu that we are working on. So basically that's the kernel it will lean on. The containers will lean on. It has one CPU, one vCPU because it's T2 micro and we have one gig. So here is showing almost one gig that we have right now. And the name of the machine is IP 17231421 177. Here is one very important thing to note which is the docker area the docker root directory. This is where docker is installed and there will be subd directories for the containers and for other stuff under this path. So it's very important to know about this. This is a docker controlled area. So it's not recommended that we play with it at all. But this is where Docker exists and this is where all the subdirectories for everything in Docker is going to exist. So let's inspect that directory. We're not going to play with it, just inspect it. So we're going to do CD and I'm going to go into here and I'm going to do ls. And as you can see build kit container it's container ID image network overlay plugins runtime swarm temp volumes. So these are all the directories for docker. Again this is a protected controlled managed by docker. So it's not recommended that you play with it. I'm just showing you where is docker installed. Of course that's the default path. You have the option to install it wherever you want. But again in that new path it's going to have all these directories and subdirectories available and that's exactly the components of docker and how it works. Not recommended to touch it. All right that's another good point that we wanted to see here. See if there is anything else worth highlighting. Yes. So when we did the docker version, we had the client as well the client. So it talked about the client and the server. So we have both. So we have docker version and docker info will give you a lot of information about the system or the docker engine that you are running right now. All right. So now we have docker installed and whether you contact it through the EC2 instance connect or remotely or through SSM it's going to be the prompt for the system that has docker. One important thing we note if you connect remotely most probably you will end up with this as the home user directory home/ Ubuntu very important to know the path if you go through SSM you will not find the home/ Ubuntu it will be just the root if you don't know you do the print the working directory and as you can see it is the home/ Ubuntu in any way you log in before you use any path do the pwd you will find where to exist right now in the system. So now we have installed Docker successfully and we are ready to roll throughout the rest of the course. All right, so it's time to get to know some basic Docker commands. So let's go ahead and introduce that in slides and then we're going to immediately apply it in the console. So theory labs theory labs and that's how we practice and we verify what the information in the theory mean exactly. So the first command we're going to introduce is the docker pull. If you are in a docker host and you would like to pull an image from docker hub. So you don't have that image you want apache you want engine x you want ibuntu you want centtos. Whatever the image that you need you don't have it locally. So you want to pull it from docker hub. The syntax of the command, it starts with docker. All the docker commands start with docker and then pull and then we have options and what's the image that you would like to pull. If you want a specific version of the image if you don't specify the tag, it's going to pull the latest version available. So here's an example. Docker pull Ubuntu then it will pull the latest version because I did not include a specific version detail here after the column then it's going to pull the latest version of Ubuntu. If I want a specific version then I'm going to docker pull Ubuntu 20 for example 04. So that is I want the Ubuntu image version 20.04 04 it will pull that specific image say also docker pull hyphen all tags so these are options now Ubuntu so pull all the versions that are available from the image Ubuntu from where from dockerhub after I pull an image how can I find out if it was pulled of course I I'm going to see some activity on the screen and then I need to know what are the images that I have on the host such that if I'm looking for one that I don't have then it will be pulled from docker hub if I have it then activities are going to run from the local image. So docker images is the command we use in case if I need to find out what images I have and that includes the images we downloaded from docker hub and the images we created locally and we can use the command docker images. It will list all the images on the local host. We can do docker images minus q. So it's not going to give me all the details. It will only list the image ids that are available. If I need to find out if I have any containers available on my machine, then I do the docker ps. But there are some options as well. List the running containers. If no options are pasted or are specified, it will list only the running containers if any or blank if there isn't any. If I do docker ps minus a or hyphen a that means tell me all the containers the stopped and the running ones. So that will give me detailed information about each container its status ID name and more information. So we can do docker ps and we can docker psyen a or I can do hyphen all and that will list all the containers running and stopped. So let's go ahead and check on the docker host what we can do with these images. We're going to visit also the docker hub and we can see where are these images and how do they look like and how can I find out about the tags and so on. So let's go ahead to the console now do some activity before we cruise through the rest of the commands. So I have connected again to the host. I'm going to do a clear sudo su. So I will have I elevate elevate the privileges basically that I have. And now I'm back into the home directory as you can see. All right. So let me do docker images to see if I have any images available on the machine. And as you may have guessed it in a previous lab when we installed Docker we looked at the hello world when we did docker run hello world right. So at that time it installed this image for me. Now if I want another one let me say I want to pull the Ubuntu image. What do I do? Docker pull Ubuntu and I did not specify any tag. So here I can specify 24.04 for example. I did not specify anything. I'll just do this. And now it's pulling from library. By default, it goes to docker.io. As you can see here, docker.io. Found the Ubuntu. And it went for the latest. Why did it go for the latest? Because I did not specify what is it exactly that I need here in this command. Let me just enlarge this a little bit. So I did not specify anything here and that's why it went on and it brought the latest one. So let me repeat the Docker images again and now we'll find out that we have Ubuntu and it's the latest and here is the image ID and it was created on dockerhub.io two weeks ago and that's the size. If I do docker pull and now I'm going to go for a specific version in Ubuntu. Let's say 24.04. It downloaded a newer image in this case. So in my case which is this one pulling from library and digest and downloaded the image for Ubuntu 24.04. If I do docker images again now I have three images. I have the latest of Ubuntu and I have the 24.04. And you can see the size and the one that I had earlier as well. All right. Now let's check for what containers I have if any on the docker host. So we can do docker ps and as you can see the docker ps without options it shows me if any running containers are available on the host and none is available. As you can see if I do docker ps minus a show me everything including the one that have are in stopped or exit state. And as you can see, we have two and these are the ones that we ran through the installation of Docker from the Hello World image and the command was hello and that was 52 minutes ago and these are random names that have been created for these containers. I could also do docker psy all and this will show me the same output. So if you look at this or I you look at this, it's exactly the same. So the minus a or the hyphen a is the short of hyphen all. So either one will get me to find out if I have any running containers on the system. Now let's go go ahead to hub.docker.com in order to find out about the available images. If you go on the left hand side, you can see Docker official images, verified publishers, and sponsored OSS. So I'm going to go into Docker official images. I'm looking for images to be more specific. And then as you can see here, Mimachd, Engine X, Busybox, Alpine, Reddus, Ubuntu. So this is what we have been pulling. And you can see last week there has been more than 4 million pulls and there is more than 1 billion downloads. I'm going to click on that. And here you can find out about overview, quick reference, supported tags and respective docker file links. And if you click on the tags, these are the available versions basically. And you will find out what's available here. And now you can see the tags 25.04 04 latest 25 24.10 24.04 and this is the command if you would like to pull the image. This is the latest one of course. And if I go to another one, a specific one like the ones we have seen, latest for example, here's the command to pull it to pull it to your machine. And if you have of course one like this, then it will be the colon and then the the tag. This is how you pull it to your machine. All right. So let's go ahead and continue our basic Docker commands journey. Docker create is to create a container from an image. You can assign the container a name if you would like to and it will be created but it will not be started. So let's look at an example. Docker create and then hyphen name. So these are the options and this is a name of your choice and then the image and you can also add a tag if you want to the image. So if you don't add a tag, it will be latest. If you add a tag, it will be the specific version that you need. If it's not available locally, it will be downloaded, pulled from hub.docker.com and then it will be downloaded and then the container will be created but not started. Right? The order is very important. So if you don't add this for example the hyphen hyphen name they will consider that you want to create a container from an image called my hyphen container. It will look for it. It will look for in docker hab it will not find it then it will give you an error. So the order is very important and when you want to add an option you have to commit to the syntax of the option as well. Okay. So this will create a container. Let me just erase this. So it will create a container with this name from engine X. That's what it will do. Here's another example. Docker create and then hyphen name my container Ubuntu and then a specific tag. So it will be created from this specific version. So that is a container created but not started. What if I want to start it? Then we go into docker start. docker start and then the options and the container and flags. So start an already created container that is not running and the container is the name of the container that you have or of course you can use the ID as well. So here's an example. Docker start my container assuming this was already created beforehand as we did in the last slide. That means please start this container for me. docker start abcd123 if you want to specify by the ID where do we get the ID from from the docker ps command and then the output will find that or docker psy a depending if it was running or stopped and we can start more than one container by the names or by the ids all right so now what if if I have a running container and I'd like to stop it for whatever reason I mean it could be troubleshooting it could be we have prepared it and it's not production yet. So, we're going to shut it down until the production time comes and then we'll bring it up again. Whatever the reason is, you can create a container using docker create, but it will not be started. You can start a created container that is not started using docker start and you can stop a running container using docker stop. So, this is going to stop the container gracefully. Gracefully means don't stop it immediately. By default, I believe it gives it like 10 seconds, but also you have an option that you can specify a longer time if you think the container will need more time to gracefully stop. If the process doesn't terminate by default, then 10 seconds it's going to stop it no matter what. You can extend it if you would like in the options. So, docker stop and then the container ID or the container name. And you can also do an option minus t to to extend the 10 seconds. Here it's 30 seconds and then my container. So if it doesn't finish within the 30 seconds, it's going to be forced to stop. And we can also stop more than one container if we want to. This is not docker. But remember at the initial lectures or we always say that containers are nothing more than a software process that runs on Linux and it has a process ID. So how can we prove this? We have multiple Linux commands not docker commands. They don't start with the word docker. ps a show all processes that are running psy a ps and then psu. And we can combine a with U and X to show the processes owners and if they are not attached to a terminal and also the process that are available on the system. All of that we are going to do. We are going to use the PS AUX in order to prove to you that actually this container or the containers you're going to work with are nothing more than a Linux process from the Linux kernel perspective. So let's go ahead and do this in the console. Let's do the docker create, docker start, docker stop and we are going to prove that also it is a software process. By the way, you have this access also to the uh script files that I'm using and these are going to guide you through each step that we are doing right now and you have access to them. So you can repeat watch the video and repeat or you can look at the script and you can do it yourself without watching the video. So, you watch the video, you understand everything. Now, it's time to practice and you have all the instructions what to expect to see and all that. So, this is more like a step-by-step guide into doing all these labs for all these commands. All right? So, I'll keep it on the side. I'm going to be doing the steps, but you can always refer to it later on and it's going to be available to you in the Docker commands YAML file. I'm going to remove this now and let's go ahead to the console. So, here I am in the console again. By the way, if you get into the instance using EC2 instance connect, you have all the right to remove this. I mean, the good thing about this is it shows the public IP and the private IP. In some labs, we might need the public IP uh to connect to the instance and other stuff. Or if you would like to connect remotely, you would need the public IP as well. But in my case, I need more screen space than the public IP. So, I'm going to remove it. All right. So let's now start with the docker create command. docker create and then we do hyphen name. You don't have to if you don't want to specify a name. And then I'm going to create it from image engine x. And I'm not going to add the colon and if I do colon latest. It's exactly if as if I did not add anything. All right. Remember we don't have the engine x available. So let's see what will happen now. So first thing unable to find image image engine X and it decided because I did not include anything here that is going to be the latest. It's not available locally. So it's pulling from the library engine X and you have pull complete for different items. We're going to discuss the details later on. And now we have a new image available on the host and the name is Engine X. Let's check docker images. And as you can see here that we have another image available engine x and it has been created not here on docker hub 7 days ago this latest version and here is the size okay but I have created an a container right. So how can we find out if we have running containers? Docker ps let me clear docker ps we don't have any running container. If I do docker ps minus a and you'll find that here that here is a container with the name count one. So we are not getting the random names anymore because we specified the name and it is created 59 seconds ago and it's from an image engine X and here is the container ID. So you have all the information but it doesn't say exited. Exited means it was running and stopped. So that's exited but created that means it's created. So how can we start it? docker start and then either we provide the container one or I could have also provided the ID. So either the name or the ID both would work without any issues. Now if I do docker PS again minus a. So now these are the first two ones that we know about but this one is up. So even if I did docker ps only, I should still see it because it's up in for 21 seconds now and the port is 80 and it's about a minute ago it was created and it is from engine X and it's the exact same ID. So ends with 2450 ends with 2450 ends with 2450. So that's the same one that was created and it's available. Now let me do a clear. Now let let me prove to you one thing. We have discussed that containers are run as software processes or processes in Linux as a software process. Software process must have a software ID. How can we find out? So let's use the Linux command ps. So that's not starting with docker. So that's a Linux command. And I'm going to write a. So tell me all the processes that are running right now. Okay. So now this is not showing what we want. So let's do ps aux. So show me basically everything. And as you can see that engine x is running. But this is not what I'm worried about. I'm worried I'm I'm concerned to find out if container one is running as a process or not. So I'm going to repeat the same command and I'm going to search instead of looking into all of this. Grab find out in this output if there is anything called count one and sure enough there is one container there is a process run by the root because I have the root privileges and this is the process ID. How do I know that this is the process ID? Let's scroll up in the command output and find out what are the different columns that we are seeing. So user P ID and then the CPU it's taking the memory it's taking and so on and the status as well. So P ID that's what I have. So we got assigned 6551 as the process ID and here as you can see the process name. So engine X is running but that's fine. Engine X is running but I was concerned about the container. How is the container functioning? And that's that proves that containers are run as software processes. All right, back to docker. So what do we need to do now? So we have a running container and we have proved that we have a running container now. Docker ps. How can we stop it? Docker stop and then either the container name or the ID. Let's go with the ID this time. And let me do a docker ps again. Oh, I'm sorry. docker ps nothing running docker ps minus a and you'll find out that this container has exited 9 seconds ago. All right. So that's about how you can use docker create docker start docker stop and we have also proven that containers run as processes on Linux or on the operating system. It's still with the Docker commands. We are going to look at the Docker exit command. What if I need to start the container and I need to run a specific command. Let's say it's a Python container. So I need to start Python 3. I need to start the Python editor basically. Or maybe it's a an Ubuntu and I would like to list content of a specific directory or a specific file. Can I pass command to a running container? And the answer is absolutely. If it is a running container, you can do that not on a stopped container. So the command is docker exit for execute and then options. We'll see some options and then what is the container ID or name and what's the command and what are the arguments for that command that you would like to pass to the container. It has to be a running container. Okay. So it can be used to interact with the container's file system or processes or environment as if you have created the container, logged into it, executed that command and then looked at the output of the command. That's exactly what we are trying to do with Docker exec. And here's an example. Docker exec the container name or it could be the ID and then the Linux command ls and then a specific path. So you'd like to list what is in this folder basically or in this directory using this command. It's very important to notice that you are now passing the command. You will see the output if there is an output and that's it. So you are not keeping the command like an interactive shell open where you can type extra commands and so on. It's not the case. So when would you use this without any options? This is when you are running non-interactive commands. So commands that don't expect input from you and you don't care about how the output would look like. So for example, ls or cat or echo. These are examples of what you can do. Let's continue with options for this command. So let's look at the minus t or the sudo tty option. This is if you'd like to see the output properly formatted on your screen. So here's an example. Docker exit my container the container ID and here's the command ls directory is amp. I would like to list the content of this directory. But here we are enabling or adding the option minus t. Please add a tty or a sudo tty where I can see the output properly formatted. If you do the previous command and this command on the same folder, the output for this one is going to be much more organized as if you are inside the shell of the container. So it will allocate a terminal or a sudo tty to run interactive commands like bash and so on within the container. And the minus like it can be written hyphen tty or hyphen t it attaches the pseudo tty to the container basically. So you get access to the feature of the TTY devices. Okay. But until now you don't really have all the input control and we'll see that in the lab. Then we have the minus I option. So the minus D gets you the proper output attaches a terminal to the container. It can keep the standard in open. can interact. You can send information or instruction or username or passwords into the container. And here's an example. Docker exit minus I my container and then cat etc host name. It's not the best example. If we have tried for example login, it would have been much better. Why? Because login expects you to enter a username and password after that. So the standard in makes sense. Or if this was a Python simulator, a Python 3 command for example, then it will add the simulator and then you can interact. But now you have the standard in but you lost the terminal. So you don't have a terminal for the output. So you'll be typing this, it goes into the container, the container responds, but you don't see the output. So it's kind of like open one way off. Minus D was open for the output, minus I is open for the input only. So you can do I or hyphen hyphen interactive. It keeps the container standard in open and allows you to send input to the container through the standard input. And this is good in case of commands that would like to receive input from you in order to complete I mean and bash maybe login would be the best example in this case. So you need to enter the username and password. What if we combine both of them minus i and minus t? You can do hyphen i hyphen t with a space in between or hyphen it. So that means you're combining both together. Keep the standard in open and please I want also to have access to the output or the TTY. So this case in this case when you do this you are actually logging into the container. So imagine what we are doing now. We are treating the container as if it was the Ubuntu host or the Docker host. And now we are logging into the prompt of that virtual little minor tiny uh computer or virtual machine. It's actually a process as we mentioned. And now you get a prompt and you can run commands in the container as if you are on a virtual machine or a server or on your laptop. So in this case you are doing two things. You're keeping the standard in out and the output as well. So you are opening or binding the input output streams and you will see that the prompt has changed. You are now officially inside the container doing activities inside the container. And here's an example cat etc cell and you will you'll see that you are you have a shell open now inside your container and you can interact with it. If you do the cat etc shells so the in and out are open but now you are only executing this command. But if you did bin bash or bash or shell or z shell depending on which image you are using and what are the available shells then you can actually get into the prompt of the container and then you can start working on it. This command the cat etc shells it will tell you which shells are available in the image you are using. So it could be bash it could be shell it could be z shell and so on. So if you if you are not sure you can just run this one. If it is Ubuntu or most of the Linux ones, you could have the bin bash or you can just write it as bash. It will give you exactly the same if bash was on the path inside the operating system. But that's more of Linux. This is not Docker. Okay. So let's go ahead to the console and let's try these commands one by one. And again the scenario that we're going to work on is available in the script that will be available to you in the course resources. So, I'm going to be looking at the file, doing the steps, but you can do it on your own from the file. You don't even have to look at the video because even the exact steps and what what they do and why we are doing them, it's all explained as you can see right here. So, taking it step by step to see what's the difference between the minus I and the minus T and so on. All right, let's go ahead to the console. All right. So, still in the console and if you recall, we ended up with container one and we have jolly deviian and anyways I mean these are the old ones. If you want to clean up everything we can do that simply with the docker rm and then the name of the container for example. So docker rm if I do docker ps minus a again you'll you'll see that container one is gone. And I can also do it by the ID docker rm. And then I can copy the ID. And I can do more than one at the same time. So now I'm going to delete both the other containers. If we check again, I don't have any containers. Nothing running and nothing stopped. Clear. Okay. And for the images, what this is what we have. We have Ubuntu, the latest 24.04 04 and the hello world latest. What if I want to delete an image? So I can do docker then I can do rmi remove image and I can then take this one for example. So the hello world now is going to be removed. All right. So if I do docker images again, now I have only the two Ubuntus. All right, let's now start what we wanted to do. We want to try and see how can we execute commands inside the container. So for that, let's go ahead and create a new container and I'm going to call it container 2 for a change and this will be from an engine X image. Okay, so now I don't have engine X locally that's why it's being downloaded now the different layers of the image. We'll talk about layers later on and as you can see there is an ID for each one and if I do docker images now I should have engine X available as well as you can see. So I have engine X and it is downloaded and so on. All right so let's do a clear. So now we need to start the container. start container 2 docker ps and as you can see we have the container up and running container 2 up 3 seconds ago and it was created 35 seconds ago and it's engine x and this is the container ID allocated okay excellent so let's execute a cat command on the container so exit no options container 2 and I'm going to do cat etc host name and here is a host name that is available in the container but again now the container if I do ps container is still running I executed that command got the output and that's it so let's do cat and let's try etc hosts as you can see the output cat ect hosts but then I have all of these are inside a file called hosts under directory etc inside the container all Right. So what if I did docker exit minus t? I want the output to be a little bit better than this if possible. And I'm going to do exit into container 2. And I'm going to do an ls command. So the ls command it's kind of as if you are inside the machine a a Linux machine and it is properly formatted. Let's prove it. Let's remove this and do the same command. So exit also container 2 ls. See the difference. So this is just like a dump of all the output all all what's available. But here it was appropriately and lined up nicely and all that. Why? Because the minus t gives me the sudoty output. So it's nicely formatted on the output. Okay. All right. Let's do a clear still with container number two. And if I do docker ps, I still have it running. And what we'll need to do now is we would like to try something else. So I have the minus t. I know that. Let's forget about options. Now let's say that I'm going to docker exit container 2 as well. But in this case, I want to run the command login. So I want to login to the container operating system. I would expect if I was on a Linux machine if I am logged into the prompt then I would get a login prompt and then I will enter the password and that's how it works. Let's do it. I don't get anything. I don't have access to the container to send in and I don't have the output as well. So let's change this and put the option minus t and see what happens. See the difference here. I didn't get anything because I don't have any options here. I get the output nicely formatted and if you notice the host name is exactly the container ID. So I'm getting this response from the container. It's asking me to login. So let's say I'm going to say just anything random engine X. I expect it to ask me for the password and then it will tell me an error. There you go. So I sent it in the container is waiting for me. I'm waiting for the container. I don't see anything. And why is that? because I don't have actually a channel into the container to send this. So, it didn't make it to the container. And since it didn't make it, although I have the TTY, nothing came out. So, what do we do then? Let's Ctrl C. Let's make sure that our container is still running. Yeah, it is still running. Let me clear the screen. And now, let's do Docker exit. But I'm going to do the interact the minus I. So now I have sending in into the container. I have the standard in that will be available to me and I'm going to still do the login. I don't see the login information again. So it looks like I'm sending information into the container, but the container doesn't have any instructions. It doesn't have any TTY attached that will display things for me. So what I can do now is I can combine both the minus I and the minus T. And let's see the difference. Now I have this. I'm going to type engine X. And guess what? Now the minus T is sending me the password because the minus I was open and this went into the container. Of course, I'm going to type whatever. I don't have this username. I'm just trying any random thing. It will take some time. Give me an error. And we are good to go. Login incorrect. See, I have still the channel open with a container and the output as well working for me. And that was the command login. So let's do Ctrl C now. And I'm going to check also that it's still running. Let me do a tricky thing now. Let me docker. And I'm going to do exit- and into container 2. And in this case, I'm going to do a cat into the file that we discussed, which is the ATC/Shells. /c/shells. Okay. Engine X does not have these command. All right. So, let's do let's do this. I'm going to do it blindly. I think it will work because I believe that Engine X has the the BIM bash and has the the bash as well. So I'm going to do bin bash and of course you can write bash only and let's try what happens. Please notice that I am on the docker host and this is the prompt. Uh my mistake we shouldn't add the cat at all. I'm just trying to start the bimbash shell. So this should not be here. And either I write bash or I write /bin/bash and see what happened now the prompt has changed from this into this and I'm a root privilege into this host. What is this host? If you go a little bit up see when we got the login what was the prompt? It was from BD2 and it ends with 22A. And now I'm in BD2 and it ends with 22A. So now I'm inside the container. And let me show you one thing also here that if you do ls, that's exactly what we have received before when we did the ls command. And if we do ps here, oh okay, the ps command is not. So we have to install some utilities to get in here. I think the ping is not available as well. Let's try 8 and ping is not available. So it is skimmed from the essential utilities but I will show you in a later lab how we can install these utilities. So we'll have troubleshooting ways inside uh the containers when we log into them. What if I want to exit? Just type exit. And if you do docker ps again you'll find that the container engine x is still up and running. As you can see docker ps minus a and I have only this container. It's in up and running. All right. So if you would like to interact with a container in and out minus it is your best friend. And you can write it docker exit by the way. Docker exit. You can write it as minus t minus i or minus i minus t if you don't want to combine them. And then this is container two. And I'm going to run bash in this in this case, not the bim bash. And you'll see that it works. And again, I am inside the container again. So if you would like to do troubleshooting, testing, installing packages, doing whatever you like inside the container, you can log into the container and do that. If you don't want to login, then you want to just ls something or cut something. You don't need all of this. You need the minus t just to get the output nicely formatted. If it is uh a command that does not need the interaction, if it was Vim or login or uh something else, then it's better to have the -ash it get into the container, do whatever you like, and then save it and exit. And that's it. So, I'm going to do exit. And here I do docker ps. Okay, let me clear docker ps. The container is still running. If you want to stop it, you know it. docker stop count two and now if you do docker ps it it's not there if I do docker ps minus a it is there and it has been exited by force because you stopped it let's continue with more docker commands and this is a very important one docker run docker run is equal to docker pull plus create plus start so basically if you do docker run and then you decide what options and you define the image and the command. If you would like to execute a command when the container runs, if the image is not locally available, it will be pulled from docker hub and it will create the container and it will start the container. So this is equivalent to the three commands docker pull, docker create and docker start. Here's an example. Docker run engine x. There is no tag here which means the latest one. This will create and start a container using latest engine x image. And if you don't have these on the docker host, then it's going to be downloaded from docker hub beforehand. You can add the options d-name or hyphen name. And you can also put a tag if you would like to when you run a container from engine X. And this is how you do it. and we'll see that in the lab. Then the prompt is going to be stuck. So basically you will not get the docker host prompt again. If you'd like to run the container in the background and you get hold back of the prompt from the docker host then you use the minusd or detached mode. So basically create the container from engine x. If engine x is not in the local host download it start the container but please give me back my docker host prompt. run it in the background in detached mode. We can also use run with the hyphen it in order to get into the container as we have seen before like in exit docker exit command. So we can do docker run- it interactive and terminal from Ubuntu and start bin bash. So you will be inside the Ubuntu container prompt or logged in and then there will be a bin bash shell or a bash shell basically open for you as well and you get the interactive so you get the input the ability to send input into the container and you get also the TTY with it and it depends on if the bash was in the path in the operating system of the container then you can just write bash withoutbinash. So these two are the same but in case if bash was not in the path then you have to define the total path /bin/bash. Now we have docker create and docker run both of them they will try to locate the image locally and if not available then they will try to get it from docker hub. If it's not on Docker Hub that means you are this is maybe a typo or the wrong name and it cannot find it and you'll get an error. So as a workflow you can start with docker run or docker pull and docker will look for the image locally. If it's not available then it will go ahead and search in the docker hub and as we mentioned it is by default docker.io. If it is on docker hub if the answer is no then you get an error. the image cannot be located or is not found. If it was on Docker Hub, then you will get into downloading the image different layers. Then the image is going to be installed on the local host. It will be available. Now if it if the command was docker run or create then it will have to create a new container from the image and it will start the container if you used the docker run. If it was only docker pull then it will stop here. If it was a docker run or docker create then it's going to create the new container. If it was docker create it will create it and that's it. It will not start it. If it was docker run then it will start it and then the container will be up and running. So docker run is the one that does the full 9 yards. Docker pull starts right here and docker create starts right here without starting the container. If the image was available locally then it will just jump into this. If it was a docker run or docker create create the container. If it was docker run then it will also started and the container will be running. Okay. So that's more or less what we have discussed but in a visual format or in a workflow format. We have also one option if you would like the container to run something specific and then it will self-destruct. So if we do this docker run hyphen rm basically that means remove or delete ubuntu is the image and then here is the command that it will do echo this will self-destruct. So what will happen here is it will echo this sentence on the screen and if you go and look for the container you will not find it running and you will not find it as well in the exited mode. It will be deleted. So why would you do this? Use it for oneoff containers. So you just need it to do something and disappear gets deleted clean up by itself. Like if you want to curl or ping or do some testing function and once it's done the container is no longer required and I don't want to go and remove it manually. Just remove it. But don't use this at all if you are talking about long-term containers. If it is a website, a database component of an application that needs to be up and running all the time. Here we have docker run it and remove Ubuntu bash. So if we don't look at this part, this is a normal command we have seen before. Docker run it Ubuntu bash that means start a bash terminal or shell inside the container. The hyphen rm once you exit it will be deleted. So create and run an Ubuntu container. Open the interactive shell into the container. Once the user exits from the shell, delete the container. All right. So let's go ahead and do this in the console. Let's work on that and see how the Docker run acts or behaves as we have seen with the previous examples. All right. So let's go ahead and play with the Docker run command. Let me now get to the console. So I'm going to go in. I'm going to use EC2 instance connect. open a new session and from the same script that we have been using before. Now we're going to start with the docker run uh stuff here. Maybe the names I will use for the containers are going to be shorter. Doesn't matter. When you see the names, choose whatever names that you would like to do, but you need to update the different commands. All right. So, what I will do now is I will do the sudo su and I'm going to do a clear I don't need this. So I can stop this as well. So I have more space. So what are going are we going to do? We are going to create an Ubuntu container. So docker run docker run and then we need to do it in I'm not going to do it in detached mode. I'm going to start without detached mode. I am going to show you the difference between using the detached mode or not. Okay. Let's say say name is con one and this will be from engine x engine x can't find the image locally because it's a new machine I told you so it will download it from docker hub and once downloaded it will start the container as you notice right now the container is up life is good but then I don't get my prompt back so I'm stuck into a container that is running now. The image is already downloaded as you can see and configuration was ready. All looks good. Start worker process. Start worker process 29. Engine X started. Everything is cool. But then I'm stuck. Well, that doesn't help. One might say, but how can I believe that the container is running? Maybe you are just bluffing, right? So, let's do one thing. Let's go ahead here and I'm going to open a new terminal, a second terminal. So this is one terminal which is stuck and this is the second one and I can open more than one. So it feel free if you would like to do testing where you do some commands on one and then you log in from another one and see what's going on. So let me do a clear now. Let me docker ps and you can see here we have a container called container one. It's engine X and it has been up for about a minute. And here is the ID. So this proves what I said that we have a container running but I'm stuck within the container. That's what happening now. And here is the name count one and engine X. So what do I do now? Then we can exit. But if you exit that means you have stopped the container. And even if I go to the other terminal and repeat the same command, we'll we'll see that there's nothing running. Docker ps minus a. You'll find that we have an exit container 15 seconds ago. So I'm going to leave that second terminal for now. Maybe we'll need it for the for the future. Okay, let me do a clear here. All right. So what do I do? I want to do exactly the same, but I don't want to be stuck in this in this case. All you need to do is docker run minus D detached mode and name if you want and if you'd like to name it that's fine. Container can I use one? Let's see. Let's find out if I can use one again. Conflict. There is an error. There is already a container even if it was stopped. And here's the ID that is already with the same name. So please if you'd like to use a name, use a different one. That's why if you don't use the hyphen hyphen name and you provide a name, then there will be a random name assigned to the container. So let's try that. I'm not going to assign it a name at all. I'm just interested to see the detached behavior and I'm going to hit enter. So now there is a random name assigned and there is an ID for the container and now I have a container running and I got the prompt back. So I can do more commands from the same terminal. How do I know that docker ps and as you can see here that we have a container running and it is from engine x. Here is the ID and it was done 14 seconds ago and a random name. Basically that's what we get here. All right. If you look here at this ID and if you look at what we got as an output here to the command. If you look at the first part, the first 12 alpha numeric characters, they will be identical to this one. So that's the container ID. All right. So that's fine. So now we know about this one. Now let's do one thing more which is trying the hyphen it into the container. Of course I can do docker exit hyphen it and I can get into this container. I can use the name or in this case let me use the ID for a change and bash. So now I got into the container and here is the ID and I have root privileges and this is the host name and I'm now inside the container. I'm going to exit now. Now let's look at docker ps again. We still have the container running. When you run from docker run and you have the container running and you get into the container and you exit as you have seen now with docker exit it doesn't terminate the container the container continues. So can I have done the same in one step instead of creating the container and then doing the exit. What if I I know from the beginning that I need to get into the container. So in that case you can do docker run- it if you want to give it a name that's fine but avoid an existing name or you will get the error up to you and then I can do engine x and then I'll do bash. So that's all this is this first command and the second command in one. Can I run this and then I can keep it in detached mode? Yes, you can. You can add a D at the end it or spacey D that means run in detached mode but keep the terminal running and please the interactive mode I need to have the ability to send information into the container and also to receive the output. Okay. So now here I can do ls and as you can see we have lots of directories. If I go let's say for example into the etc folder and I do ls you'll find here that we have hosts for example I can do cat hosts and then you'll find the information about IP addresses and stuff like that so for example the container now has this IP address but this is not the time to talk about this I'm not going to talk about networking now the time will come when we'll talk about it all right so I can do exit now I'm outside the container. Let's do docker ps. I still have the container up and running in my case. Oh, that's the other container. I'm sorry, that's the previous one. If we do docker ps, I'm looking I should be looking at container 2. So container 2 when you do the docker run hyphen it and you get into the container and then you exit. See what happened now? The container stopped. Whereas when we did the docker the the docker run where was it right here when we did the docker run in detached mode and then I I got into it into it with a docker exit it did not terminate the container that's why we have one running right now. So what if I wanted to stop the other container? It's very easy. Do docker stop and the container ID. So we have to do docker ps first because we don't know the name. The name was a random one. I can choose this name if I want to. And then I can do docker stop. And if I do now docker ps there is none working. And if I do docker ps minus a then you'll find that container 2 and the elastic board and container one they all all have stopped. Let's do a clear. All right. So let's do one more example. So docker run hyphen it and then what we'll do is I'm going to do name container 3 because I used one and two. You can just use any names you'd like and this one I'm going to run it from python image and the command I want to run once this this is uh started is bin bash. So I'm going to get into the shell bash shell with interactive terminal in order to get into the container. So notice that this is the prompt we have right now and I will hit enter. The Python image is not available locally. So it will download it and as you can see different layers of the image. We're going to talk about layers later on. It's downloading one by one as you can see and they have different sizes. So now what I'm doing, believe it or not, I'm getting Python inside the container. That's what we are doing right now. And not only that, we have downloaded that and also the container has started and now we are inside the container. So this is the container itself. All right. So what do I do now? Let's update So now I'm working inside the container as if it is a Linux machine. If you notice I'm using Linux command Ubuntu commands because the container has access to the kernel, right? We said we are sharing the operating system and the operating system is Ubuntu. So that's why I'm using Ubuntu commands without any problems inside the container right now. But of course not the full list of commands. This will be a many set of commands that are available. Now let's do apt upgrade. Yes, I need to continue. See package lists, dependencies, reading state information, calculating upgrade packing. All right, so let's do a clear. That's too much in the screen. All right. So what do I need to do now? I need to do ps to see the processes that are running. I have the ps itself and I have bash running. So this proves that the command we executed when we created the container has started a bash process inside uh the container. Okay, that's fine. Then what do we need to do now? Now we have Python, right? Let's run the editor. So this is now talking about this Python version and this is the editor. So Python is running. If I do 1 + 1, you'll get the result is two. Okay, let's do 2 * 5 and the answer is 10. Let's do print. All these are basic Python commands. And I'm going to do hello world. You'll find that it is printing hello world. If I want to exit, I'll do this and just the parenthesis. So now I'm out. And if I do exit again, I'm outside the container. Now let's do if the container is up or or down. The container went down. Now because we did the run hyphen it and when we get into the container, then you exit and it goes away. All right. So let's do a docker ps. So now the container has stopped. But if you do a docker ps minus a, you'll find that the container is available. The python container is still available. What if I wanted to do a one-off job and I want the container to disappear afterwards? So, here's what we'll do. We'll do the another container. Let me let me u use container 4 for example and I'm going to use the hyphen rm. So, remove upon exit and I'm going to do this and start. So, the container is started. I am inside the container right now. What if I do an exit now or let me before I do this let me check from here to make sure that it is running. I have container 4 running as you can see. Now if I go here and I do exit and then I repeat the command here I don't see anything running. If I do minus a I will not find container 4 exited as before. It has been deleted. still with Docker basic commands and we're going to look at Docker inspect. A very good command that is used to find detailed low-level information about containers. You can use it with containers. That's one usage. You can use it with images, you can use it with volumes, and you can use it with networks. The output is going to be in JSON format. So, what kind of low level details about containers you're talking about? What are the mounting of volumes if there are any? What's the IP address that the container has? and a lot more information about that as well. So this is for the containers. How about the images? The details of the image, layers of the image, volumes, tell me details about the volume, the size of the volume and so on. So we are going to use it extensively throughout the course, but it's good to introduce it right now so we are familiar with it. So we can do the inspect when it comes to containers. You can do it for running or for stopped container. So a stopped container can be inspected. You're only inspecting it. You're not trying to do traffic through it or anything else. And here's the usage. We can do docker inspect and the name of the container. Of course, the ID is also or can be done docker inspect engine x latest. So, so this is for a container and this is for the image and you can put the engine x latest or a specific version or just remove the column and latest and it will be understood that this is the latest. we'll get information like image ID, creation time, and more than that. Okay, so let's go ahead and try the Docker inspect command. So I'm at the Docker host. I'm going to connect. I'm going to use EC to connect. You know what? Let's let's try session manager for a change. So let me do this. All right. So session manager this time. I'm going to show you that they could be either one for as long as you are comfortable with one of them that's fine. So here's the prompt the dollar sign and what we'll do is sudo su and I'm going to do cd and I'm going to go back to the root. Now if you do pwd you'll be at the root folder and here you can see that we are at the root and here's the private IP address of the instance. All right and I have root privileges. I've elevated my privileges. So now I can do any commands I would like. Okay. So let's do docker ps. I don't have any running containers. docker ps minus a. And then now we have let me just minimize it a little bit so we can see the containers. So this is ah it's not the perfect output. You know what? Let me shift to the other one. This is container three and then container two and container one. I would rather see it on a one line and this is not going to help. Maximizing or minimizing is not going to help. So let me I'm going to leave this for second terminal but I'm going to go and do an EC2 instance connect one. And I think the output is better organized on the EC2 instance connect one. All right. So, let me do a clear. Let me do a sudo su. And if I do pwd, see here I am at the /home/obuntu. Whereas on the systems manager, I was at the root. So, please pay attention to the differences if you are if you decide to use the session manager instead of the EC2 instance connect. All right. Okay. So, what do I need to do now? As we mentioned docker ps minus a and as you can see we have container one container 2 container 3 and elastic borg and all of them they have exited about 20 hours ago. All right. Okay. What do you want to do? So we do we want to do docker inspect container one for example. So we have plenty different pages of output. So all of this is the output and that's why we said low-level details about the container. So this is the output of the command when we inspect a container. Let's find out few fields that are going to be beneficial and we're going to look at them later on as well. First of all, if you look here, we did container one. So this is the ID, right? E6 and it it ends with 092. So you'll find it here that you have the ID the exact same. This and this are exactly the same. So that's the ID of the container when it was created. So that was created close to 20 hours ago in and then we have the arguments the engine X and if we look here you'll find that it is from engine X actually status exited and the image where it was created from and notice now when we're talking about resolve conf path host name path any path inside the container see where it starts under the var lib docker. This is where the docker will be installed and any folders that has to do with docker are going to be subd directories from that folder or from that path. So here we have the containers path for example they all start with vl docker vlib docker. All right. Name container one. Platform is Linux. Networks. We're going to look at that. And the port bindings if any. We're going to look at that later on. But this is an important part that we should also look at when we are inspecting for networking. And if we scroll down path graph drivers mounts is very important. if we have any volumes attached to the container and the image engine X volumes we don't have any volumes attached to it right now and if we scroll down more network settings information about the network and the network is a bridge and as we scroll down oh we don't have any IP address assignment right now because it is in exited mode all right DS DNS name and a lot of other things that are important. So let's bring this container to life. So let's do docker start count one. So now it has started. Let me docker ps to verify. Yeah, it has started. So let me repeat the same command again and see the network part. What will be the difference? Oh, I'm sorry, not start. Inspect. Okay, see for the network part you'll find now that we have a MAC address, a layer 2 network address and then we have an IP address on the container and we have a gateway for the container which was null before. So this is important because now we can see that when it is active it has networking components. We are going to cover a full section on networking so don't worry about that. All right so that's docker inspect and also we can do docker inspect for images. So I can do engine X and now I'm inspecting an image. So we have here type and we have layers in the image. We're going to talk about layers later on. Let's go up and find from the start what information we got. So here is where we started. So the ID of the image configuration host name domain name and all that we don't have any information about that path engine x version and the command that executes when the container runs is engine x to start engine x. Basically we don't have any volumes and labels. The maintainer of this is engineext docker maintainers docker-mineext.com and the OS is Linux the size and that's it and metadata last tag time. All right, let's conclude our discussion about basic Docker commands with Docker RM. If you would like to move a container, remove means delete, completely move it or remove it from your containers on the Docker host. Docker RM and the name of the container is going to only remove the stop containers, not the running ones. What if I need to remove also the running ones? Then I need to have the hyphen f or the -ashf which is force the removal or the delete. Here's an example. Docker rm. I can put the container ID or the container name. And I can do multiple containers at the same time. And I can only add from the ids the first few letters if I would like to. And minus f is to force stop the running containers and then delete it. What if I need to remove images? Then I have docker rmi remove image. So these can remove one or more docker images from the local system. But if I have a dependent container on one of the images, it will not be removed. Again, minus f means remove the image. Even if there are containers stopped or running created from that image. Here's an example. Docker RMI my image and Docker RMI multiple images and Docker RMI minus F remove the image force the removal that has dependent container created from it. All right, the next command is docker logs and then we have options and the container ID. This is to read logs of a container. Basically logs are important if you are doing debugging, if you are doing tr troubleshooting or we want to monitor logs for application or for processes running in the container. Here's an example. Docker logs my container and docker logs and follow my container. So that means it will display the logs and keep updating the terminal the output with the logs with the new logs not just getting me what is in the container and that's it. What if I need an option for a docker run but I don't remember it. So you can do docker hyphen help or you can do docker specific command hyphen help. So for example docker run double hyphen or d-help. This will give me the list of available option and flags for this command. So I can do it with docker commit. I can do it with docker inspect and so on. Then if I have images that are not used and I would like to free up space on the docker host then I can do the command docker image prune. So this is going to remove the images that I'm not using. Let's go ahead and do this in the hands-on lab. So let's see what images and containers we have. Okay minus a. So we have container one, two, three and we have this random container and they are from Ubuntu, EngineX, Python and Bash. So what images do we have? We have the Ubuntu utilities engine X, Python, Ubuntu and Bash. So we have these images and we have this. Let's say you would like to clear up space on the host because there are some images that you are not using. So you can easily do docker rmi and then the name of the image. So if we have this python unable to remove repository python there is a container using it. That's why you cannot remove it because we have one here that is from python. All right. So what do I need to do then? Then I can force removal rmi minus f and the image name. And now as you can see it is removing that. And if I do docker docker images now python is gone although there is one container dependent on it and it's still here. Let's do docker rmi remove multiple in and I I'll do minus f because there are containers dependent on them. I'm going to remove the bash. I'm going to remove the Ubuntu and I'm going to remove the engine X docker images. I'm going to retain this one because as you know that this one is having the tools that I usually use. So I'm going to keep this one. I'm not going to remove. Now let's go ahead and check what can we do with the containers. Docker rm. This is for the container. And then I'm going I can do 0cc. So the first three letters from this one and 5d7 which is the first d three letters from the second one. So now I'm removing two containers at the same time. Let me see what happens. Docker ps minus a and we have container two and three. So this one and this one are now are removed. Okay, let me start one of the stopped ones and then I'm going to see what happens with the container when it is running and I'm trying to let me run a container docker run minus it. Let's say name is container 5. And I'm going to run it from this image, the one that is left here. and 1.1. So we have to put the tag as well because this is what I have here. So I'm going to run this one in a bash shell. So I have it right here. Okay. And I'm going to open a new window, new terminal, and I'm going to try and remove it. So it is running and I'm going to try and remove it and see what happens because I want to show you that you can do the minus f command or the minus f option to the command sudo su and then docker ps docker ps. Okay. So I'm going to do docker rm container 5 and let's see what happens. So you can't because the container is running. So I can either stop it and then remove it or I can do docker rm minus f container 5 and it's going to kill container 5. So docker ps now I don't have anyone running docker ps minus a and now we have two containers running. I can remove them in one shot. Now I can do container two, container three or I can use the first the the container ids or the first few letters from each ID. And now we don't have any containers left stopped or running. And I have only one image left which is the one that has the ping and curl and all that stuff that we used before. Now let's try the docker help. Let's say I am stuck with docker run or docker commit and I'm not sure what options I can use with this command. So I can do docker help and then it will tell you that you can do minus a to add the author minus c to apply docker file instructions minus m to add a commit message to post container during commit. So these are the available options and here it gives you the syntax. So, docker container commit or docker commit and then the name of the container here and the image that you're going to create from it. All right. All right. Now, let's move to the next one which is the docker logs. So, I have a script for you. So, we're going to run a container with this script. It's a long command that's why I'm copying it. So docker run itd interactive detached mode name is container logs and the image is alpine and then it shell it will run a shell command while true do date it will print the date sleep for two seconds until the two seconds are done then there will be logs in the container so alpine doesn't exist it will have to download it so for two seconds it will be printing the date And now what we need to do is I need to do docker logs and the name of the container. We have to docker ps first. So we'll do docker ps and I'm going to do docker logs and the ID of the container. And you'll see now it was printing the logs. This course would never be possible without your support. In order to support us develop more free content that is high quality at no price to you like this one, consider buying the full package of this course on www.dined.com. It can be found at this address www.dlphinet.com/courses/doccker. Very easy URL to follow. And for a price of a lunch or even less with the inflation that we are living in right now, you can support us develop more free and quality content like this one to help you throughout your learning journey and to help the masses as well across the globe. If you buy the full VIP package, as I like to call it, you're going to have lifetime access to the content and its updates. It's going to be split into video lectures. So you don't have to be overwhelmed with seven or eight hours or even 15 hours a single video. You can have that divided into separate lectures for theory and hands-on. You are going to have access to the full 15 hours version of this course and you're going also to have additional hands-on labs on the topics that we have covered but at at a deeper level. You'll have a second realworld capstone project that will deepen your real world experience with Docker and also you'll have a community access to that community for faster Q&A support and of course the ability on our platform to have quizzes and assignments is going to be there as well. And also you'll have access to the scripts for all the hands-on labs and the 330 pages PDF guide that includes all the slides of this course. We appreciate your support if you can and that would definitely be a good return on investment to yourself as well through more free content that we can generate through your support. When using Docker, it is very handy to use an IDE, an interactive development environment like VS Code. I mean it's up to you if you want to use a different one but I'm going to show you where you download VS Code from from Microsoft. It's free and also how to you can install the Docker extension is because we are going to use it in our demonstrations moving forward. So if you head to Google and you just type VS code download and you'll find the official website visualstudio.com download. Click on that and then here you'll find out the Windows installation and then you'll have the Mac installation and if you are working on a specific Linux image as well. Okay. So if you click on Windows for example then you'll find that the a direct download link is going to start or if it's not started you can click the link. So this will download the package and then you can just double click it if you are on Windows and then you can follow the instructions and yes yes yes continue and add the user agreement and then you'll have the file add the shortcut to the desktop and life is good. So you have VS code. Now the next one is we need to open VS code and we need to install the Docker extension. So it will help you as you write Docker code basically or Docker scripts. So let's go ahead and do this. So if you are in VS Code, what you need to do is you need to click on this which is the extensions and then here you would like to look for Docker and this is the one that we are looking for edit smarter ship faster and so on. In my case this is already installed so I can uninstall it and disable it. So it's installed and enabled. In your case, if you didn't have it before, then you will have here install. Click on install. It will take some time and it will be installed. Make sure that after that is done, then here it's going to show disable and uninstalled. If this is what you can do, that means it is installed and enabled. So, if this one shows enabled, please click on it. If it shows disabled, don't do anything. You are good to go. If this one shows install, that means you need to click on it to install it. If it shows uninstall, you're good to go. Don't do anything. So, you're looking at that it should be exactly like it shows here. And the auto update in case if there are any updates, you can do that as well. All right. So, we need the one from Docker, not from Microsoft, not from any other ones, the one from Docker. And you need to install it and make sure that it's enabled. That's it for this hands-on. Please install Visual Code and please install the Docker extension. Let's look now at how you yourself can customize a Docker file based on what application you are using. So for example, you would like to run an application that is written in JavaScript. Has nothing to do with the base images that are available except for the fact that you need to run it on Ubuntu or Alpine or Fedora or Red Hat Enterprise Linux whatever the base image is. But then you have a lot of files and dependencies and code that you would like to upload. So now you are customizing an image. How can you write the text file which is the docker file from which you can use the docker build command to build an image and then you can use that image for creating your production of course de development testing and production environment eventually and also using the same technique whenever there is an update to the code or update to the dependencies or the runtime version that you would like to use you can go back into your docker file create a new version. So now you are maintaining that let's say in GitHub in a repository version two and then update whatever you like create from version two image two and then from that you can build also new containers and then you can decide on how the migration will happen. So the essence is building and customizing your docker file from which everything else happens and this is what we're going to discuss right now. A docker file is nothing more than a text document and in that text document you tell the docker engine all the commands that a user would have otherwise done manually on the command line to build the application. So what we are trying to say here is the instructions in the docker file are nothing more than the actual commands that you would have used manually on the CLI to build your application. So if I wasn't going to use containers and I wanted to build the same application using command line, I would have done that step by step manually in the command line. Let's say start a virtual machine Ubuntu virtual machine and then go into the console and start as the root user or as a privileged user to do make directory cd copy run apt update yum install and all that stuff. That's exactly what we do. But we would like that to be automated and that's why we build the docker files. So how would a simple docker file look like? This is an example where we are instructing docker please build an image that is going to download the base image from Ubuntu. And I could of course include colon and then a specific tag for a version if I wanted to who created this docker file and that will be in the image as well the details of who created that the author basically. And then I want to execute the command apt apt get update. So I want to run this command. And then at the end please execute this command. Echo hello from dolphin ad. So that's a very basic and simple docker file. But as you can see it's all text. You can write it in your preferred editor or maybe in VS code or any other IDE in order to give you help with the Docker plugins and all that. And you can build it and life is good. Very easy. And from that you are going to save it as a Docker file and then you execute it with a Docker build and boom you have an image. Docker can build these images automatically by reading the instructions from a Docker file. And how does that happen? When we have the Docker file edited and saved, then we can use the Docker build command. And in the docker build command instruct it or let it know where is the docker file. So it will read the instructions and it will create a docker image. That's how simple the whole process is. So let's understand the syntax. I mean we have here from all all uppercase maintainer all uppercase run all uppercase cmd all uppercase. What does each one of these mean and also what are the other options that we could use. So let's go ahead and start to investigate that. So let's start with the very first one. The docker command or the docker file instruction from the from is nothing more than letting docker get the base image on top of which the image is going to be built. So the syntax is from and then the name of the image and the tag or the version in case there is a version to be followed. Let's say I have after that run I have command and I have other instructions. So all these instructions will be based on the image that we have downloaded or created a layer for in the image based on the from instruction. So this one for example from Ubuntu means since there is no colon and tag that means please pull the latest B Ubuntu image and the following instructions are going to be based on Ubuntu. When you have a Docker file that has multiple instructions, when an image is built, Docker is going to build each line in the Docker file, each instruction in the Docker file as a separate layer in the resulting image. So for example, here if we have a Docker image that has four layers, this could be corresponding to the file that we had. So the from is going to map to a layer. The maintainer is going to map to a layer. The run will map to a layer and the command will map to the layer. Why is that? Why is it built in this structure? And that's a long story about the union file system that the docker images use. But the point simply is if you have these segregated from each other then if you want to build a derivative from this image let's say I go later on and then I change the author and this will be John Doe plus George Watson. So now it will update the corresponding layer only without having to impact or download or change the other layers. So the new image will will reuse the existing layers but will only change the one for which a change has happened in the docker file. So that's the simplest the layman terms of why it is layered and we're going to play with the layers also in the hands-on labs. Second instruction we need to look at is the run. So remember from B image now if you have any run commands they will be run based on that B image. So run will run one or more commands normal commands that you would have otherwise done manually. So the run instruction will execute any commands in a new image layer and commit the results and the syntax is run and then you put the command or commands there could be multiple commands not only one. So here's an example I have a statement in my docker file. So let's say we started with from Ubuntu as we did in the previous one then run apt get update. So this command is based on the fact that we are starting with Ubuntu. If it was Alpine, maybe it was going to be apt with a K, not apt. If it was Red Hat Enterprise Linux or Rocky Linux, for example, this would have been yum. So, it all depends on which base image and then what will be the commands that you would have used manually on that base image or operating system if you will. So run apt get update and then run apt get install and yes for any questions vim and I can do also get I can do echo I can do nano and other tools that I might need to use as well. So these are two instructions and they will end up being two different layers in the resulting image. All right. Is there a way I can minimize the number of layers by combining run commands? And the answer is absolutely. This is actually not the recommended way because now you are creating multiple layers for no reason. And the recommended way would be that you can combine both. So you can have the two amperands which means do this command and this command to install them and this command to install get and you can have more than one. So all of these is going to translate into one layer in the resulting image. So fewer image layers. One might ask but is it a rule that we try to minimize the layers as much as we can? This is all based on what is it that you are doing. So if you want to run different packages and you know that down the road one of them is going to be changing frequently which will result in that this layer will have to be run again and again and executed in every update then maybe you would think no no no I don't want to do that uh for Vim I don't want it to be updated regularly so I'm going to separate it in a separate run command and the others I'm going to combine them. So minimizing the layers is sometimes a very good idea and sometimes it is required to have multiple and separate layers depending on the frequency of the updates. The docker history command can help you find out what are the layers in the base image if you will or in the resulting image that you have created and you can use it to inspect the layers available or the layer details in any image. very handy to use when you would like to find out what is the number of layers available and what do they map to exactly in the instructions in the docker file. So very easy docker history and the name of the image that you are using that you have on the local host and it will tell you everything about it. Still with docker files let's look at the cmd or the command instruction in a docker file and also how we can build images using the docker build command the command or cmd. So this is to specify the command to be executed when the container is started. If you think about it run that was maybe installing uh something updating something that is run command when the container runs what is the command that will be started is it bin bash shell terminal is it going to run engine x is it going to do an echo command that's what we mean by to be executed when the container starts and the syntax is we have command and then I mean this is the JSON and the preferred way then we have the brackets the square brackets and Then what is the command? So this could be echo for example, can be ls, can be something else and then parameter 1, parameter 2 and so on. Usually only one command instruction should exist in a docker file. But what if I am building this image from an image that already has a command and I would like to add a command in my file. What happens? If you have multiple ones, then the latest one is going to be the one that will be executed. So only one will be executed. The weak side of the command is that it can be overridden at container start time. Don't rush it. I'm going to show you that in the hands-on maps. Here's one example. Command square brackets. And then we have the double quotes echo. So this is the command to be executed. And here is the message that will be echoed. So this is the parameter for the command. And the output after the container runs will be hello from dolphinet. That's it. And if we have another example, if this is the command that will be executed when the resulting image from this docker file is going to execute when we run a new container. So that will be the command to be executed when a container from the image is created at the start time. And this will execute Python command and the argument. Okay, Python will run to do what? To run the app.py the code that is in this file. So this will run Python app. py at the container start time. Now let's contrast command and run. We don't want to leave any confusion. So run is going to execute at the build time when the image is being built. That is called the build time. When we are creating a container from the image, this is called the runtime. So we have to separate the two. Building the image from the docker file is build time. Creating a container from the image is runtime. So at build time if you want to execute commands update, yum install and so on. This is the run command and what it is used for and it will add layers to the images and it is used to install apps and tools and so on. executed at runtime is the command. So when we start the container, this is where the statement is effective and it runs a command at the container when it is started. /bin/bash echo lsc cat whatever that is. Now we have already built our docker file and now we would like to translate that into an image. What do we do? So you can use the docker build command and you can pass options to it and the path the path is the build context which is the files you need. You want to copy these files into the container. You would like to move the app. py into the container because it will be executed. So this is called the build context and the build context area is usually protected by docker. So for example, if I do docker build minus t. So that's part of the options. Minus T means tag. Provide the image this tag or this name. And you could have versions as well if you wanted colon and 1.0, 1.2, 1.3 and so on. And the dot here means that the current directory on the local host is where all the files and all the build documents or data that you need in order to execute the docker file. All right. So where is the name of the docker file? You don't have to specify it if the default name is used which is docker file one word with a d in uppercase and the options as we mentioned flags you can pass to customize the build. So minus d is one of the options that we have used and then by default docker looks for a file named docker file. What if the d was a lower case? It may work but it is looking for a file with no extensions and it is one word docker file with a capital D. Okay. Can we specify a different name? Of course you can and that is easy to do as well and we're going to look at it right now. So let's say if the path as we mentioned is the build context and usually the current directory. What if it is in a different directory? What if on the local host I have copied everything under a different directory? everything in terms of the app. py if it's a python application any requirements any configuration details any path any dependencies I have put them in a folder specific to that application I am and it is not my current directory on the local host how do I refer to that that's one thing the second thing is what if I'm using a file with a different name I I mean I have lots of applications and it doesn't make any sense that I'm going to call them all docker file I want to call it app one for the first look file app2.ext text for the second app xyz doty yamel if I'm in that situation which is very logical what can I do so here is one example if we have a docker file with the name test and it is available in a child directory from the current working directory called files and the build context everything that has to do with the build the app py the code and so on is going to be in a also a child directory under the working directory called image files. Then this is now different because the minus f is going to tell docker and by the way when you build your file that you should be looking at is a subdirectory under the current directory and the file name is test.ext and minus t that's another option. Please tag the resulting image with this name and you can have the version if you want it. And oh by the way when you need any files that are going to be copied and so on into the container you will find these data that is under the subdirectory under the current directory called image files. So that's how easy we can interpret this. And here is a more complicated one because in the path here I can use relative and I can use absolute. So here is one with the absolute uh details docker build minus f. So this is the file I want but the file is under home Ubuntu. That's the home user directory under apps subdirectory under image files and test.ext. That's where it exists. And that's the docker file you should be looking for. And then please tag it with this image name. And by the way, the build context where you'll find all the documents that needs to be copied is going to be under home Ubuntu. That's the home user directory under build under context files. These are the subdirectories nested and then a directory called app one. So you can have all the flexibility in specifying where is your docker file and where is your build context because you need to structure your file system. It cannot be a mess and you cannot put all the files for all the applications and then in one directory as the build context and you cannot name all the files as docker file because one will override the other and eventually you're going to lose your data. So I have my docker host. I'm going to connect to it and I'm going to start a terminal and it's always handy to start a second terminal that we might need throughout the labs as well. So I'll have both of them ready and in both of them what I will do is I'm going to type the sudo su and I'm gonna do a clear and I'm ready to go. And of course you know that we are working on the home Ubuntu directory. Same thing here. So do su and clear and we're good to go. All right. So we have the instructions that we are going to use and again it's available to you as part of the script. All right. So here is what we are going to use. Let me minimize this so we can focus on the screen. So this will be the demo for the Docker file. We'll start with a very simple Docker file. So I'm going to follow the instructions in the file with you. You can follow along with me and then you can do the instructions yourself. Okay. So I'm going to remove this so you can see everything I'm doing. All right. Right. So here I am in the AWS console and I am on the docker host and I have done the sudo su and I'm with the root privileges now and I have another terminal that is exactly the same. So what do we need to do? First thing let's make sure that we don't have anything on this directory clean directory and let's do docker images and we'll see that we don't have any images except the one that I created long time ago. And if we do docker ps minus a, I don't have any containers running or stopped. So what do we need to do? I need to nano or vim a docker file. And here is the name capital d docker file. So what do you need to do here? I'm going to start from an alpine very light base image. And what I will do is I'm going to use the command or this is the command that will execute when the container is created and it runs. It will be the echo command and the argument that I'm going to provide is welcome and another argument hello from dolphin ad academy and we close this and we are done. So, Ctrl X, this is for nano. Press Y and hit enter. And if we would like to make sure that we got it right, then I'm going to cat the content of the file. And as you can see, here we go. From Alpine echo this. So, let's build the image. Docker build. Tag it with the name image one. And the building context is the current directory. There are no files to copy or anything. So it doesn't matter. I'm going to do it the current directory. So now you can see that it has done it very quickly because we have a very small command. Basically there is nothing to download. There is nothing to update. There is nothing to take time. That's why it finished very quickly. And what we'll do now is I want to do docker images to make sure that it has been created. And you'll find that image one is created. And the size is very small because Alpine is very small. clear and then what we can do now is we can do docker history I'm going to start with the alpine I would like to see the layers in the alpine the base image we have used okay so we don't have it locally so what I will do is I'm going to pull it alpine because we need to look at the original content or layers and then I'm going to compare it to the new one to the one that we created So I'm going to do docker history alpine now. And as it shows here there is one layer two months ago and it's an add instruction in the docker file and it is alpine mini roots fs and at the end it is compressed. We're going to talk about the ad later on. Briefly the ad instruction what it does is it's going to copy the content and will decompress it. So it will unzip it basically untar the file. And then we have the layer which is the command bin bash. So Alpine in itself if I run a container straight from the alpine image it's going to run the bin bash I'm sorry the bin shell not the bin bash the bin shell command. And here we have image metadata but here we don't have it and that's because it's downloaded. It's very common when you download an image and you do docker history that there will be missing lines. missing it doesn't mean the content is missing. And the proof is here is a size but the metadata is missing. That's that's what's missing now. Okay. So these are the layers we have in the original alpine that I pulled the latest one. So now let's do docker history but for the image we have created image one you'll find the original ones the original two layers and as you can see now two layers are missing the information the metadata basically and then we have a new one which is the echo welcome from dolphin ad. So this is what we have now. So if we build a container let me clear if I build a container. So, docker run and I'm going to create it straight from image one without name without anything. What do you expect to see? Welcome. Hello from Dolphinet Academy which was exactly the content of the docker file. If we c it again docker file. So the echo command was executed and then it appended this as an argument and this as an argument and that's where we ended or how we ended with welcome hello from academy. All right. So this is our first file that we have and I can do docker ps minus a. We don't need this container anymore. So I can do docker rm and then b a5 the first three letter from the id ba5 and it's going to remove it. If I repeat the command now it won't have anything running or uh exited. All right. So let's create another docker file. So let me remove the docker file that we have or you can edit it. It's up to you. I can delete this or I can edit it if you want. Let's go ahead and edit it. Maybe it's a better idea. So nano docker file. So we have our file in nano. If you would like to delete a line, you do ct controll ktrl k again. The file name is still docker file. As you can see the file still exists but now it's empty. So what we are going to do now? I'm going to create another image. You have it in the script from Ubuntu. Of course, you can go and do 2204 for example, if you would like to if you have a specific version because before we did from Alpine without any versions, it brought in the latest. So, let's do this one. And what I will do is I'm going to run because it is Ubuntu. I'm going to do apt get update. And then I'm going to do another run at get install minus y and I'm going to install them and run again apt get install minus y and we can download git for example and at the end I'm going to add a command and the command would be simply again echo And the argument is going to be this is an Ubuntu image with Vim and get installed or we can state Ubuntu container because we will see the message when we get the container. Doesn't matter what you want to write. I just want to make it relevant. That's it. Crl + X and I'm going to save the modifications. Hit enter. And if you would like to check the file, docker file and it is from Ubuntu. App get update up get install up get install and echo. All right. I don't have the Ubuntu image 2204 as you can see. So what we'll do is beforehand let me clear and let me docker pull and I'm going to get the same Ubuntu and 220 or so now it's pulling it. Let me just make sure that we got the right one. CD docker file 2204 and we downloaded 2204. Yeah. So we are right. docker build minus t. So I need to build a new image. Let's call it image 2. And this is again from a file that is on the local directories. That's why I did not add here anything about minus a for file name. And the building context there are no files to copy or anything. So everything is going to be on the same directory and hit enter. Now you can see that there are a lot of steps. So here is run apt get update run apt get install minus y vim. Once this is finished it's going to become run get apt install minus y get and then the command of course is going to be added but it will will not see anything here. When we run the container, we're going to see the impact of the command exporting to image exporting layers. As you can see, so layers have been created and they are being exported. And here you can see the steps. So step number one, step number two, step number three, step number four. What you don't see is step number five. Okay. So let's do docker history. And now I want to see the layers in image two. Let's see what we we have here. So we have the command echo. This is an Ubuntu container with whatever run apt get install run apt get install them run update and then the bin the bin shell. So these ones are not in my file. Where did they come from? So we have the command and we have the three runs and it was from Exactly. It was from Ubuntu. So these ones must be coming from Ubuntu. Also if you notice here there is a command that was already in whatever that has to do with these layers. So what we need to do is I can do docker history and then Ubuntu 22.04. Let's compare this here to these lines here. So the count is 1 2 3 4 5 6 and the count here is 1 2 3 4 5 6 and they are exactly identical and it ends with the bin bash and we have the label orgo open label or open arg launchpad build and arg release. So the layers from the original base image plus the layers from my file are both added as if the from Ubuntu has added these layers because it's bringing them from Ubuntu and then the the other instructions in the file have built the other four layers. All right. So let me clear it and let me do a docker run- it and I'm going to build a container and this will be from image 2 and I would like to execute the bin bash. So I want basically to get into the container I would like to make sure that vim is present and also get is present. So now if we do on the other terminal just to make sure that this container is running docker ps I have a container running 8 seconds ago created from image 2 and it is running bin bash and if I get here and I want to in to try vim abc.ext so it works it somehow halted. So what I will do is I'm going to docker ps minus a. So we have it running. I'm going to stop it. And the ID of the container for some reason them has stopped. So now it's stopping the container. All right. So if I do docker ps minus a again, the container has stopped. Now let me get into the container again. docker start and the name of the container or the ID. So I'm going to start it and then now I can do docker exit minus it and again the container. Oh, I I didn't put the command. So I'm going to do bash. Now I'm inside the container again. All right. And I want to check if I have get hyphen version and I have get installed already. And if I want to check them without having to get into it again, I can do which vim. And then it shows me that is installed. So this is what we have seen based on the image that we have created. Still with docker files. Let's now have a look at the expose and copy instructions or docker file commands that we can use. Let's start with the expose one. So the expose only informs docker that the container is supposed to or listens on the port at runtime. So it is expose and then the port or it can be multiple ports. And here's an example expose 80. That means the docker file informs docker that the container we are talking about in this docker file is exposing or supposed to listen at port 80. And if we do expose 80443 and if we do at space 443 that means two ports the container will listen on two ports 80 and 443 for example. Okay. Now what's the reality of exposing? Does it really expose? like does it do the mapping and publishing and the linking between the container port and the host port and the answer is no it doesn't. So the expose isformational only if you are running manually and building images manually and all that it's not going to do the publishing of the port or link the host to the container. So it does not actually publish or expose the port open to the host. So you have to do that with the docker run hyphen p or hyphen publish that we have discussed before. However, for tools that autogenerate configurations like docker compose like docker swarm and kubernetus these tools they can do the required configuration based on the exposed instruction in the docker file. So it is useful to do anyways if you are using these tools. If not, at least it isformational. Anybody looking at the Docker file will find out what is the port to expose and maybe they will use the hyphen P and then the mapping between the host port and the container port. The second instruction we're going to look at what if I need to copy the code of the Python application I'm working on inside the container when it runs. So it will be available inside the image and then when I create the container it will be available. What if I have any dependencies any requirements any environment data that I need to pass anything else that the container needs to run. So one way to do that is to use the copy instruction. So it will copy new files or directories from a source which is on the docker host to a destination that will be in the image and eventually in the container file system at the path specified as destination. The copy command can only copy files or directories from the build context which is protected by docker and not from the outside. So you cannot download it from a storage somewhere in AWS for example using the copy command. Let's take an example to understand. Let's say on the docker host you have this project structure. So on the current directory you are at right now let's say it is the /home/obuntu for example. Then you have created a docker file. It is straight under the same directory that you are at right now. Then you have created a folder called app and under the folder app which is under the current directory you have a file called main. py. So that could be the application Python code and under the app directory you have created another subdirectory called utils and under utils you have a file called helper py. So this is the structure of the project that you have on your docker host not in the container not in the image. So we haven't used the docker file to build the image yet. We need now to put the copy command inside the docker file to reference what is in the build context and then decide where it will end up in the docker image and eventually in the container file system. So how would we do that? Let's look at the example. So we have this example. I mean this is a snippet of a docker file. So we could have any instructions or commands from and run run run run and and that stuff. So we're going to copy from app utils and I don't have any file name here. So I have this is a relative path. So from the current directory there is a folder called app and yes there is one and underneath that there is a folder called utils and yes there is one. So I'm going to copy this directory with its contents completely. I'm going to copy it in the image and in the file sim. So this is the destination and this is the source. So I'm going to take it from here all the content of the utilities directory. I'm going to copy it in the image file system in the container file system under / app/code/utils. So if these are not existing it will be they will be created in the image a / app/codes. All right. So that's the first one. So the app utils directory is going to be copied under app code utils inside the image and I could have more snippets and then I decide to copy the main application. So now I do a copy from where I am right now. There is a sub directory or a directory called app and underneath there is a file called main. py. So this one is going to take all the content in the utils directory whether it is one file as we see here or multiple files. But in this one I'm only copying the main py and I'm going to take it to the slash app/code in the image. So not / appcode utils that's a different path one step higher or the parent of the utils child directory. Why did I do them in two separate commands? I could have just copied everything local and throw it in the file system. This is where we get back to the layers that we are talking about. When you segregate that then actually if there is any change at any point in time in the future in the code only then only this layer is going to be impacted or this instruction because the rest is going to be as is. So it is cached no changes nothing will be touched but this one will be the one that will be updated in the image. So the caching and speeding up the image creation by using cached data that did not change in the new docker files. All right so hopefully this is clear and it clarifies how the copy works and please note that it cannot copy files from anywhere. It will be from within the build context anywhere within the build context but not anywhere else outside. Let's do a quick hands-on lab on expose and copy instructions to understand how they work and their impact in a docker file. All right. So here I am and I have the two terminals open. What I will do now is let's do ls. So I don't have any docker files or anything. So let's create a docker file and we want to demonstrate how expose works. So nano docker file and I'm going to do from engine x and expose 80. That's it. So that's all I'm going to do in the file. Ctrl X. Yes. And enter. Now let's build the image. Build minus t. Let's call it image expose. And the build context is going to be the local one. All right. So I have this built. And now if we do docker images, I'm going to find one here called image exp which is right here. Image exp. Let me copy that because we are going to use it. And now let's build a container from that. So docker run image exp. So now we have engine x running. I can double check from here. docker ps and I have one running from this image image mgxp 7 seconds ago. All right. So what do I need to do? First of all, if you look here, there is no mapping at all for the ports. There is no publishing for the ports. Yeah, but how can we guarantee? That's fine. Let's go ahead and do one thing. So here is the public IP address that I have. Or you can go in here and you can copy it from here, whichever you like. Let me open a new browser. And I'm going, of course, by default it's HTTP, but I want to write it so you can see it. And I'm going to try an access on port 80. Can't access it. So, how about if I try it from the command line? If I do curl and then I'm going to HTTP into the private IP address of the host. And that would be on port 80. And if you don't have it here, if you are not using the EC2 instance connect or you closed this before, then you can also get the private IP address from here. Can just click on these squares and you will copy it. And if I try this, I'm getting an error as well. So as if that the expose in the docker file was onlyformational and we did the docker build manually. So we are not docker compose we haven't used docker swarm it's not kubernetus. So they did not look and generate the required configuration for that to work. So looks like it's a failure and we couldn't get access. So let me stop this container and do I'm going to do ctrl c. Now if we do docker ps I shouldn't find any active. Let's do a clear. And what I will do now is I'm going to do docker run. I'm going to do minus p. And I'm going to map port 80 on the host to port 80 on the container. And this is going to be from image I think if I'm not mistaken it was image exp. All right. So I'm going now to map port 80 on the host to port 80 on the container. And this is the image we are creating this container from. If I hit enter, I have now engine x container running. If I move to the other container and if I do here from the other terminal, we are going to check docker ps. And yes, I have one running and it's up. And you can see here the difference. So the previous container when you look at the ports they were just talking about the port that the container is listening on but here you can see that there is a mapping from the local host on port 80 to port 80 on the container and this is for IPv4 and this is for IPv6. So no matter how you will come into the container on into the docker host using port 80 you should be able to make it into the container. Let's check. Let me refresh this. And here you go. Welcome to engine X. So now you can see that expose in the docker file is onlyformational. And you have to do the publishing yourself or you have to use a tool that will get that piece of information from the docker file and then do the required configuration when it is creating the containers in order to expose or publish the port between the container to be mapped to a host port. All right. So I think that is clear. So let's do a Ctrl C. And here I'm going to do a clear and let's move into the copy part of what we need to do. Okay. So let's create a file called test.ext. Hi. This is testing the copy command. And I'm going to do Ctrl X. Yes. And save it. If I do ls, I have the docker file and I have a test.ext available on the local directory. That's what I have now. So let's go ahead and remove the existing docker file. I could have edited that but let's me let me just remove it. ls. So I have only the test.ext file. So now let's do one thing. Let's do a nano docker file. And I'm going to create from Ubuntu this time. And we can do run apt get updates just a filler. And then we are going to do copy. I want to take the test.ext and move it into a specific path within the container. So what we'll do is I'm going to copy test.ext. So it will understand that this is available on the local directory. I could have also done it this way or I could just leave it this way. Both should work. So this is the source. So where do you want to take it? What's the destination? I could have enter. So it will be on the root of the container. Or I can do in a directory called app. So if it doesn't exist, create it for me and copy the file into it. Or let's choose another one. copy test app. So this is going to be the folder. So we are not going to confuse it with any default ones that are going to be in the container. And what I will do also I can do cmd cmd and echo testing copy. All right. So this is my docker file. I'm going to do ctrl x yes and hit enter. Let's do cat to the file to make sure that it has what we need. So from Ubuntu run apt update and then it's going to copy this into a new directory that is going to create and then cmd echo testing copy. This could be unnecessary. I could have just ignored it completely. So let's build the image. I'm going to call it image copy. And it's in the the build context is the local directory. And when I do this, that means that test.ext is in the local directory as well. So it's going to search for it when I do the copy in the local directory. All right. So docker images and we have the image copy here and that's the size and we can do a clear. And now let's do docker run. I want to get into the container to verify that that directory has been created. and the copy has been also executed and the file test.ext exists on the container. Okay, so docker run minus it and then image copy and I'm going to run bash. So now if we do ls you'll find that we have the directory copy test app and if we do ls copy test app you'll find that there is a file called test.ext text and if I do cat copy test app test.ext hi this is testing from or testing the copy command. All right. So it's very clear how handy you can use the copy command because you want to add your application, you want to add your code, you want to add your dependencies, requirements, files and so on and that are these are going to be inside the container because when the code runs then it needs to access all these information and these data and of course the code needs to be existing as well. All right. Hopefully that makes it clear and it's easy to assimilate. Still with Docker files and we are still with the Docker file instructions. We are going to look at work directory or work dire and we're going to look at M and the label instructions. So let's dive straight in. That takes us to the third instruction which is work directory. What if I need to move within the file system or do like a cd and then a path within the image path or the the container file system path while I'm writing the docker file. So work directory is used to define the working directory of the docker container at any given time and the syntax is work dire and the path that you would like to move within the image p file system or eventually the container file system. So the work dire will create the directory specified by path and runs the following container commands. So when you do the work dire this is equivalent to as if you are in the container and you have done cd and then the name or the path and if the directory is not available this becomes equivalent to as if you did m a mk or make directory and then the name of the directory and moving into that directory as well. So as if you did make directory and you moved into it. So make directory and cd or if the directory is existing because of a previous work directory then maybe it's only a cd. So any commands will come afterwards until you hit another work directory they are going to be implemented into that path within the image and the container. So if you copy files they will be copied in that new work directory or the one that you have created and moved into. So let's look at an example when you do work dire. So this is a snippet again. I mean this there could be commands in the docker file before and after work d / app that means if the slash app directory exists move into it. So anything that I'm going to tell you underneath this until you hit another work directory instruction will be under the slash app and the slash is abs this is absolute. So from the root from where it starts under app directory and if it doesn't exist create it the path in the syntax that refers to the image and eventually to the container file system. It does not mean the host that you are working on. It's not like the copy source the source path was on the host and then the destination was in the file system of the image. This is 100% for the image file system which will be the container file system. So the path will be in the resulting image during the build time and in the container during runtime. So this is very important such that you don't get confused. So let's look at a real example that actually uses copy and work directory so we can understand it better than before. So the exact same project structure on the docker host we have the working directory. It could be /home/ Ubuntu. And I have a Docker file under the same directory. And then I have a folder called app main.py under this is a file under the app subdirectory or directory. And then I have another nested subdirectory under the app directory that has a file called helper.py. Here is what we are going to do. So we are going to load it from Python 3. I believe this is a flask version if I'm not mistaken the slim one. Then we are going to create a working directory where so working directory is talking about exactly the image and eventually the container from that image not the local host. So if the slash user/source SL app so basically from the root this is an absolute path create them if they don't exist. I want directory from the root called usr user and a subdirectory under that directory called source and then a subdirectory under that called app. So if I want to draw it in the container, it's going to be the root. And then under the root, we are going to have user and then under user, I'm going to have a folder called src. And then under src, I'm going to have a folder called app. And then I can have files under that app or unders. So I have this level, this level, this level all nested together. And this is the root of the container. That's exactly what I did here. And what we need to do now is we need to to copy the content of the utils directory. Copy is source and destination. Source is the docker host. Destination is exactly is the container image and eventually the container. So I want to move this but I want to move it under user source app code. Okay. So under user source app I also have another directory from here called code and under code I have one directory called utils. So this is the structure that I have in mind and the commands are going to facilitate this. So the work directory user source app is going to create this and this and this and also since I did this now inside the file system of the container it is as if I have moved so I created all of this and I have moved here so any relative path that I'm going to provide should be starting from the app any absolute path can start from the beginning but I can start from the app directory because this has moved me inside the image or the image to be to the app level. So now I'm going to do copy app/utils and this is going to be copied at user source app code utils and if this doesn't exist it will be created. So now the content is going to be moved and it's going to be under utils. So what it will will be available here that will be the helper py that's is what will be copied here. Now all right so this is done now but we are still here from a work directory and from a file system perspective however we have provided the absolute path so it cannot confuse it another way I could have done it is just slashcode /utils or codeutills and it would have understood that I'm talking about this and about this if I wanted to go with the relative path not the absolute path now I want to copy just the main py file and I'm going to move it into user source app code. How can I do this? Copy from this that's a relative path according to the current directory from a subdirectory under wherever I am in the file system on the docker host from the app uh directory please copy main.p py where are you going to move it? I could have said since I am right here in the image file system I could have said code slash and that's it. But here we provided the full absolute path. So from app/main. py please move it into user source app code. So underneath this directory there will be the main. py and this is in the resulting image and in the resulting container from that image. So now we have moved our code as we like it to be. So the application itself is going to be under code and any utilities any is going to be under utils which is a subdirectory from code. Now I would like to set the container directory from here I would like to shift it to here. So we can do this using another work directory that will move me one step lower in the hierarchy as if I did cd space code. So get me into the code directory or subdirectory in this tree. So how would you do this? I would do work directory/ user/source/ app/code. So this was going to be the container initial working directory when we start the container. So if I log into the container. So we create the image and then we create a container from the image and if I do docker exit and I get into the container and do the command pwd I should see that I am at the / user/source/ app/code that will be the meaning of what we are doing here then what do you want to do then I want to run a command what's the command that you would like to run this is a python code right so it makes sense that I'm going to either use entry point or use command and the command will be python 3 and The application I would like to run is main. py. If you didn't do the work directory, then you should have added that it is under code /ain. py in order for the path to be right. Otherwise, you'll get an error. We preferred that we move into that directory beforehand so we can just do main. py and it works. So hopefully this is clear right now on how copy and work directory they function together. And here's another docker instruction called environment. So that allows for setting environment variables for the docker container. The syntax is env and then the key and the value for that key. That's how we write it. So here's an example. We have env name equals dolphin at. So this is the key and that's the value assigned to that key. So now as if I'm defining a variable and a value to the variable. So now whenever I use it within the docker file, I don't have to rewrite dolphin ad again. So I can just do command echo and then dollar sign the key and that will immediately as if I am referencing the dolphin ad parameter. So imagine this is an IP address that you would like to use it or a URL that you would like to use it or a parameter or port data that you are using multiple times inside the docker file then you can reference it once in the environment and then just use its name as a variable. So this one when we create an image and from which we create a container the container will echo dolphin ed which is the corresponding value. So what if we would like to override the defaults or the values that we have assigned to the keys in the in commands in the docker file. Can we do this? And the answer is absolutely you can do this. And here's an example. What we need to do is we will we need to build a container that will do some let's say TCP IP checking or HTTP checking. So for that one we're going to run two env commands. One is going to be for the action equals pink. Here is the key. Here is the value. And the other one target equals 8.8.8.8. So two keys and two values assigned one to each. And then we are going to run the command shell. The image is alpine and treat the string here as a command. So that will be execute and assign process ID one dollar sign action. So basically the value of action and dollar sign target the value of target that's the default. If I don't do anything else this is what will be executed. So let's build the image and then we are going to execute it now to run a container because we need to ping a specific target. So for that one we can do docker run my image and that's it. By the way, the Alpine is a very light image and usually it doesn't have the ping and the curl installed. So that's why run app this is in Alpine. This is similar to run app get install in Ubuntu. So Abuttails is going to install pink and curl is going to be installed by this one. Now if I would like to use curl to a specific IP address, what do I do? Then we can override the default value ping for the action by using the hyphen e with the docker run command. It's an option for docker run. So action equals curl. That means please take curl as the value for action. Do not take the default one. And please take minus e also minus environment target. So the environment target take the value for that as 10.10.1.1 instead of 8.8.8.8 8 my image and the output is going to be without the E option at runtime we know that is that is going to be ping 8.8.8 but with this command it will be curl 1010.1.1 the shell will invoke a shell inside the container and the minus C tells the shell to run the following string as a command. So this string is going to be run as a command. All right. So the label instruction has been used now after the maintainer or the author has been deprecated. So the label is to put a label metadata basically to your image while you are creating it. So you can add metadata to an image. So the label is going to be in the docker file another instruction. The metadata that you can add includes a lot of things. It could be including who's the author, who's the maintainer, what's the version, what's the email of or the telephone number of the team that supports it, environment, production or else other custom data that you like and it should be written as key value and here's an example label and the key is owner and what is between the codes is all the value. So, Dolphinet Academy team and here's the email team at supportthedalfphanet.com and we could have a phone number or a WhatsApp number and so on. Let's now do a hands-on lab to demonstrate the instructions in the Docker file work directory environment or M and label and how they work. Let's get to the console. All right, so ls I have here the docker file and test.ext. So, let me go ahead and remove the docker file. All right. And I'm going to remove also the test.ext. So as usual, I have the two terminals and I have cleaned completely the docker host. So if you look at docker images, you'll find only a few left. And if we do docker ps minus a, you'll find that there are no containers active up or exited. All right. So, let me clear. And if I do ls as well, I don't have any files available on the docker host. So, what do we need to do? I need to explain three different commands today. And again, everything is available in your script. I'm trying to follow the same steps because it will make it easier for you as well to follow along if you watch the video or if you want to reference the script. And all the scripts are going to be available to you. So, don't worry about that. All right. So what do we need to do? We need to create a docker file. And now we are going to demonstrate the work directory. And here I'm going to start from Ubuntu. So we are going to do work directory and / app. So basically as if I'm instructing docker when the container is to going to be run that please create an app directory that is below the root directory. Then we're going to run echo command. And what we will echo is this is the / app directory. And this will be redirected into uh file. Let's call it app.ext. So the same name as the folder. All right. So that's one run command. Then we're going to do another work directory. So I'm going to create a path within. I'm going to say / app slashcode for example. And then we're going to run an echo command again. Run echo. And similarly we're going to state that this is the / app slash app slashcode code directory directory. And also we're going to redirect that into a file called code.ext or we can do even appcode.ext. All right. And then we can do an echo although it's not that important in the command or I can do just ls at the end. ls. So I don't have to provide any parameters or any arguments. And I'm going to do a control x yes to save and enter to get out. And let's do a docker uh a cat to the docker file. And here it is from Ubuntu work directory. So cd basically into an app directory and then create this file. And then it's going to do a cd again into code and then it will create this file and it will do an ls when I run the container. Okay, that's fine. Docker build minus t image work dire and it is in the current directory. The building context is in the current directory. It sounds good. Docker images. We have it. What a short name. I'm going to copy it because I need it. Clear docker run- it and the image. And the command we are going to execute is bash. So I'm now inside the container. Have you noticed what happened now? The last thing we did in the docker file was I mean we moved into the app directory with the first work dire/app and then we did another work dire /app /code. So it had created an app folder under the root and then a code directory under the app directory and now I am into that path inside the container. All right. So let's see let's me do ls and you have the app code text. So let's cut this file app hyphen code dot text dot text text. Yeah. And you find that this is the app code directory. So not only the directory and subdirectory have been created but also the app code file and also the redirection of the echo output in the run command into this file. So let's do a cd move one step up in the hierarchy and you'll find that we moved now into the app directory. If I do ls then we have a directory called code which we were in and we went one uh step up and then there is the app text. So if I cat the app.ext.ext then this is the app directory. All right. So that explains to you how you can control your working directory using the docker file. I do exit now. Now let's the docker file and let me change the default starting path. How would you do this? I'm going here to add a command that says work directory and I'm going to start at the app but I'm going to call it database for example. So now we moved into app and then we moved into app code and now I'm going to move into app database. That is one thing I can do as well. All right. So let's do Ctrl X Y enter. And I'm going to build the image again. And I'm going to build the image again. We'll call it amage work dire 2 the build context. So dot docker images and we have it work dire 2. I'm going to copy the name clear and let's start a new container docker run minus it and the image name and I'm going to do a pwd so print the working directory you'll find that we are into the app database so we are not we didn't open the interactive I mean if I didn't have this it would have worked as well but here it tells you that the default of the container is app database how can Let me confirm. I'm going to do bash. And here we go. So you started at the app database. So this is very clear how the work directory work as if you are moving moving and you can build your file system the way you like it and the way you would expect it to run when the container is created from that image. Hopefully this is clear. All right. Let's now go ahead and do the M and label. So here we go. I have the two terminals available and ls I don't have any files available. What are we going to do? I want to do them both in one docker file. So let's nano a new docker file and it's going to be from Ubuntu. And I'm going to run app get update and I'm going to also run app get install minus y. And what I need to install is the IP IP utils ping because we need to use ping in this case. And I'm going to do m and I'm going to call action equals ping and target is going to be 8.8.8.8. So what what I'm trying to do is when the container runs I would like to ping the IP address 8.8.8.8 8 basically sending messages to that IP address and waiting for responses or an echo response. 8.8.8.8 is the Google DNS server and it's available on the internet and anybody with connectivity to the internet can ping it. All of that is good. Then I'm going to do label. Who is the maintainer? Who created this? Who is the author? And I would say dolphin ad docker team. And we need to execute the command. So we're going to use bit of a complicated format. So it's going to be shell expansive. And I'm going to have the minus C for what will be uh implemented. And for this one we are going to use the dollar sign action and dollar sign target and then we close this. So basically what I'm trying to do is when this runs it's going to install the ping utility inside the container and these two are like variables a variable called action equals ping. So that's the key and the value and there is another one target key and the value and the label is only going to talk about metadata of the image and then we have the cmd. The cmd is going to run this as a shell. So it's going to have the action which is ping and then it's going to run the target which is 8.8.8.8. So basically these are going to be replaced and this is going to be the command to be executed in the shell. All right. So let's do ctrl x yes enter. And we're going to build the image minus t. I'm going to call it image one, two, three for simplicity. And the build context is the local. All right. It has a minor comment about the label. We're going to look at that later on. Docker run. And then I'm going to run this from the image. Image one, two, three. Let's see what happens. Let me nano the file again. All right. I think I know where the problem is. This does not exist. So I'm going to do Ctrl X. Yes. And try again. Docker build minus T. Correct. I'm going to call it. And the build context is local. Docker run. Correct. And as you can see the container has started. And now it is pinging 8.8.8.8. So it has worked. It was only the square bracket, the extra one that I have added. But you have it correct in your syntax. So don't worry about that. And it shows that the container has started and the cmd is pinging now the DNS in Google. All right. Of course, I will not be able to stop it from here. So what I will do is I'm going to do on the other one on the other terminal. That's why it's handy docker ps. And I have the container running. So I can stop the container or I can just remove it because I don't need it anymore. So 182 the first three letter from the container ID and I have to do minus f because it is running and now it should stop. So if I go back you'll find that I'm back. The prompt is here again. All right. So that explains the label and explains the m. So let's nano the docker file and look at the problem we have seen the label issue that it didn't like and what it expects is it doesn't expect to see the input this way it has to be in a key value format. So let's do maintainer and it equals and I'm going to say dolphin ed academy team. And if we want also we can add an email. So let's say for example dolphin adolphin.com. So this way it's not going to complain about it. And let's verify. Ctrl X. Yes. And let's do a docker build. If it doesn't complain, then we should be fine. Minus t image 1 2 3 4 and local. Yeah, it didn't complain about it, which is good. Let's do docker inspect and image 1 2 3 4. And if we look at labels, yeah, see labels maintainer, dolphin head academy team and the email. So now all is cool, everything is good and this is how it should be written. Now let's talk about docker images and docker registry. I think we have covered a lot about Docker images already. But a quick recap and then we'll head into Docker registry. How can we create our images but then not stop at that point but we can push it into a repo of our own. It could be a public one, it could be a private one or we have already pushed images and now it's time to pull images from our own repo public or private. So let's go ahead and start with this. Let's start first with Docker images. A quick recap. We have already covered a lot of information about that. Please remember that we called the build time which is where we have a docker file and then we build an image from the docker file using the docker build command. So we have the docker file from which we can use the docker build command and then we can tag the image with the name we need and then we define where the build context is and what it will do what docker will do is it's going to go ahead and create different layers one corresponding to each of the commands in the docker file and of course from this will not bring one layer it could bring one two three seven 19 layers depending on how How many layers does the image you are pulling from contain? So how many layers basically that image includes? Image layers when you build it are read only. So you cannot edit them. If you need to make a change, you will have to update your docker file and then you'll have to create a new image with a docker build command. So docker image layers, what's the best practice? what to do with these layers in order to optimize the image. So you need to group the copy and run wisely to improve layer caching. So if you have multiple copy commands, can you combine them and at the same time you are sure that these are not going to change frequently in one or two layers or less number of layers in a way that caching is going to be effective and at the same time it will not change every time like these layers will not change every time you make a change. You need to put less frequently changed lines early like installing dependencies for example. So up in the docker file after the from if you have less frequently changing dependencies for example downloads then put this at the top. Avoid unnecessary run commands to reduce layer count and image size. Like in the examples we have seen when we do run app get update and then a separate line run app get install minus y vim and then a third line apt run apt get install minus y get and then run. So you can combine these into one. So they will be one layer and you will enhance the image size and so on. So back to the best practices again. Let's see what is the goal and what is better and why. For example, if you would like to have fast builds, the image does not take much time. Then we need more layer because that will have the different details cached. And now if we would like to build again, a lot of the cached stuff will not be rebuilt again. It will be reused and then we'll only build the new stuff or the changed stuff. So this will allow Docker to skip unchanged layers. If you need smaller images, then we need fewer layers and clean builds. Why? Because this is going to have fewer intermediate file sizes or layers. We need to enhance the maintainability readable layers. So we need easier debugging and edits. So this will be easier for readability and that means easier debugging and edits. For layer reusability, what's better is to split steps logically. So it's not always to reduce the layers. Maybe you will split the steps because you would like to reuse and when you reuse, you would like caching to be effective as well. So in that case, maybe you will have more layers and that will have base images that can be reused and cached. All right? So it's not like one way, but now you have the best practice. Keep it in mind. Of course, fast builds are important, smaller images are important, maintainability is important and also reusability is very important. So from the build time we take it to runtime and this is when we start to create our containers or the execution phase of the containers. So the image we have built is going to be used to create the container and execute the command or the entry point command that is in the image or the if we can override it then the one provided at runtime basically and that will create the container once the container is created if we have an exit interactive shell into the container. So these are locked because they are only readable or read only but then we might do an update. I might install another tool ping touch or one that I will need. In that case I can create more layer using these commands and these will be writable container layers because they are not part of the image. I have created them when I created the container manually. Please remember the image tag the image version basically that we can tag images as we upload them or as we pull them as well. we can tag what we need to pull or when we are uploading them to docker hub we can also or to the docker registry we can also decide this is version one this is version two this is version three and we can have also messages that goes with that or metadata that would would state why did you do the change so if we do docker run postgress 10 10 anything after the colon is the image version if we don't add anything that becomes the latest. But if we do this then what will happen is if I don't have it locally that means docker is going to go ahead and get version 10.10 and if we do docker run for that one you will see that it could not find it locally and now it is pulling it and it's pulling its layers as well. Whereas if we do docker run postgress without the colon latest or with the colon latest it's the same thing it will go ahead and pull the latest version of postgress. If we have done that beforehand what you will see here is some of the layers are not going to be pulled again because they do exist. So if they did exist on your local system, they will be reused because of the caching and now it will only pull the layers that didn't exist or they are different than 1010 and postgress 1010 will do the same assuming that 11:15 was the latest for example. Let's now discuss docker registries. This is the place where we store the images. So this is where we push the images we created from our virtual machines or our laptops into the registry such that it's going to be available to everyone else that is allowed to access it and use it. If it was public registry then everyone with the right command can pull that from your registry. If it was a private registry then anyone who can login or access or have credentials to get to the registry would be able to pull the images. So pushing images as we mentioned if we would like to visualize this is basically about having an image created somewhere and then you need to do a docker push and the docker push command is going to take that and then push it to the repository in the registry that you have specified by default and the most common one that everyone uses and it's available for everyone is docker hub and in docker hub we can have under your account it can be a public repo or multiple public repos or you can have one private repo if it was a free account or multiple private repos if it was a paid account. There is a specific naming convention for Docker images that helps with organizing versioning and discovery of images. What's the naming convention? It's exactly as we see here. So the registry name or the DNS of the registry and then we have the account or the organization and then we have the repository and a tag. So the repository can be the image name as well. So let's get to know each one of them in more details. The registry is optional. Why optional? Because if I'm dealing with Docker Hub, I don't need to specify it. It defaults to docker.io. That's the default. Otherwise, if you have a registry that you have established inside your corporate or you're using something else other than Docker Hub, then you'd like to add the domain of the container registry. Basically, how can we resolve that to an IP address to find out where is your registry then the second part this is the name of the user or organization and it is required for nonofficial images only. official images like EngineX, Ubuntu, Red Hat, CentOS, Fedora, Alpine. These are all known official images from Docker. Then they don't need the organization and we don't need the registry because they are on Docker already. Then we have the third part which is the repository and that is either the name of the image or the project. For example, production e-commerce that's a name of a project or it could be app 1, app 2, app 3. So that's the name of the image and then we can have a tag as well because we need to maintain versions of that as changes happen and if you don't add a version or a tag it will default to latest if that is not included. So let's say I have an image called ABC. Is there a way I can create or rename or create an alias of that with the correct name that is that follows the naming convention uh for Docker images? And the answer is absolutely and that's the docker tag command. So the syntax is docker tag and then the source image and the corresponding tag if this is what you need to rename and then the target image the new name and in the new name you can control to make it according to the naming convention of the docker images and then a tag if required. Here's an example docker tag python 3.10. I'm going to change the name to my Python hyphen app and latest. This is general usage. So using the tag command to create an alias or to add a name to an image does not mean this is only if you want to push images to a docker registry. You can or you may want to change the name and use the new name. It will be the same image. It will not be copied. It will not create a new image. But there will be another name for the image that it can be accessed through. Now if we would like to use the docker tag with docker registries. So the motivation now is we would like to push or upload the image to a docker registry. So we have now to follow the naming convention. So in that case you will use the source name and tag if any and then we are going to follow the naming convention. So it we have to specify the registry unless if it is docker hub then we don't need to then what's the username or the account and the repo tag that's for the image and repo which account and which repo to use in that account and what will be the tag or the version of that. This is only about tagging changing the name creating an alias. This is not the actual push. Let's look at examples. Dogger tag my app. So this is the source image. There is no colon latest or any version. So it will be considered as latest. And this is it's not docker hub. So that's the registry that we are going to use. So this is the domain of the registry. And this is the account. And here is the image name. And I would like to tag it with this version. So I maintained the image name as is. So I have a repo on this registry called my app and this is the version that I would like to tag it with. So this will tag the image my app with the name registry.mmyorp.com devops my app 1000. So this becomes the new name or the alias of this image and this is what we are going to use when we try to push because it will tell the demon where we are going to upload it under which account and what's the name of the repo. To push commands into a registry you have to login or authenticate otherwise anyone will be able to push images into your registry. to push images into your registry whether it is public or private doesn't matter you have to authenticate with the registry so you have to have credentials to be able to upload or push into the registry and the way you do this is very simple from the CLI on the docker host docker login and then the name of the registry then you will be prompted for the username and the password and then you will be authenticated once that is successful you will be able to push to the registry If we are working with docker hub registry the docker tag command we don't need to put or to add the registry domain. So it will be only docker tag local image name and the local tag and then the username on docker hub and the repo and tag on dockerhub. So why didn't I add the registry? Because it defaults to docker.io as we mentioned before. So it will be simpler name that you are using or the alias name is going to be simpler by one step. No registry details. Here's an example. Docker tag my image. This is the account I have on docker hub and that will be the repo. Please note that they don't have to be the same name. So they may or may not be the same name. And then the version on docker hub in the repo. So this is going to be the latest. So my image is tagged in preparation of pushing to docker hub registry. How did we know it's Docker Hub? I did not specify anything here. So it will default to docker.io. Under this account under the repo my app with the tag latest. The local image name and the repo name can be the same. They do not have to as we mentioned. So here is another one that docker tag my image and then my username my app version one. So this is if you wanted the latest and this is if you wanted to add version one to be pushed basically or it will be prepared to be pushed as version one. Okay. So now we did the tag whether it was with a registry that has nothing to do with docker hub or it is with docker hub. Now how can we do the actual push the actual upload to that registry is using the docker push command. So the docker push syntax is docker push registry host. This part is not needed in case if you are working with docker hub and then the username and then the image or repo. This has to come after you have done the first step which is docker tag. So you do docker tag first. You rename the image properly and then you push it. So you are not here trying to rename anything. you have already tagged it and it's available and now it's time to push it to uh docker hub or else depending on whether you included the the registry host or not. So here's an example for dockerhub docker push my app and then my username my app latest. What if it is a generic registry not docker hub something else then you will tag the image properly in the previous step and now push it with this name or the alias which you have done beforehand and you included the registry with it as well. So this is the account and this is the repo. Now putting all this stuff together what is a docker image life cycle? So we're just recapping everything we learned about docker images. So starting from a docker file, we can use docker build in order to establish an image. But of course beforehand we must have a local host or a docker host available. So docker build will help us create the image or we can pull an existing image if you would like to from docker hub or maybe because we're using from Ubuntu so this part is going to be pulled if I don't have it locally. Now we end up with the docker image. From the docker image we can do docker run or docker create. Then we end up with a container. If you use docker run it will be active running. If you use docker create it will be stopped. Then we can stop start or restart the container. And we can do docker commit. If we did some changes and we'd like to create a new image, we can do docker commit. Of course, it's always advisable that you update the docker file and then you use the docker build to create a new version of the image. And of course, we can tag it using the docker tag command and then we can push it to docker hub just to maintain it there so it's not dependent on a virtual machine or a docker host that may fail and then the image will be lost. We are going to demonstrate how we can push images that we have to docker registry and also how to pull images from the docker registry if needed. So what we are going to do is we have dockerhub and we have showed how we can create an account on docker hub and we are going to establish an image or create an image on the docker host. So let's call that dh docker host. Once we have the image ready, then we can push it to the Docker Hub repo of our choice. So let's go ahead and do this in the Docker Hub host console. So here I am logged into the terminal for the Docker host and from a previous lab we had an application, a Python application that had a Docker file and the rest of the data. If you would like to look at the Docker file, we can basically nano and then the Docker file. I think I did a mistake. There was an R missing docker file. So here is the Docker file. So we're not going to change anything. I'm going to create an image from this. So I'm calling docker build minus T and I'm going to call it repo image. Of course, I did not specify the build context. So, it's going to be local. We do docker images. I will find that I have a repo image right here and it's latest because I didn't tag it with anything and it's 8 mgabytes because it's from Alpine. Now, what I need to do is I need to move it into Docker Hub. I need to push it to DockerHub. So, in order to push it to a Docker Hub, I need to tag it in the format of DockerHub, right? So let's check the DockerHub account that we have. So we'll go to hub.docker.com. I'm not signed in at all as you can see. So there are multiple ways to do this, but let me sign in the normal way first. The password. So now I am into docker hub and as you can see we don't have a repos available. I can create one from here or when you are pushing you can create that. So docker hub will create that for you if you are logged into this. So what I can do is I can state that this is going to to be called app one for example. You can add a short description. This is the Python Python app that is created using Python Flask framework and I'm going to hit on create. So now we have the repo but as you can see we don't have any images. It's blank. And the repo name here is the account lab user 0701 and app one. This is enough if I would like to push an image into it because it's in docker. All right. So we have seen that we have the repo available and what we need to do now is again a last look at the images and as you can see we have the repo image available. So what I need to do now is I need to tag it because I need to push it into the Docker Hub repository that we have created. One thing you need to notice here that if I go back to repositories that you can tell whether this is a public or a private repo from here from the actual folder or the actual section of the repositories. So let me go back here and what we'll do now is I'm going to tag this repo the repo image with lab user 701 / app 1 which is the name that we have created right here and I can do this as version one. So let's see what happens. Now let's go back to images. You'll find that I have one here and the tag is version one. But you will notice that the ID is exactly the same like the previous one. And this proves that this is nothing more than a reference, a link or an alias to the original one. Even the size is exactly the same. All right. So now let me nano the docker file and I'm going to make a slight change and let's say for this one I'm going to say that the command is echo and we are going to echo this is app one version two x yes and Enter. So now we have a different Docker file. So what I will do is I'm going to build a second image and this is also going to be called repo image. In this case it's version two. And this is what happens in production. We are simulating what happens. A change happens or a change is needed. We go update the docker file and then we create a new image. And then if this is going to be production or a lot of people need to access it and also to secure that image, we push it into DockerHub. That's what we always do. Okay, the build context. So now we have the second image and if I do docker images, I'll find that I have repo version two. So what I need is I want to eventually be able to push it as well. So I'm going to tag it repo image version two and I'm going to tag it with lab user one version two as well. So it's the same application but this is a different version. And if I do docker images again so what do we see here? Let's analyze this. So repo image that was the original one from which we created version one. They both share 100% the same image ID. Then we created a repo image version two and that has a new ID because it there was a change made and that's a new image a new actual image and this is the reference or the alias of the new actual image. So now we have two different original images and two different aliases and now I can think about why don't I go ahead and start to push them. Okay, so let's clear. All right, what do I need to do now? I need to start pushing the images. So let me do docker images again. And now I will start to push and I would like to push this first one first v1. So it is preparing now but at the end it did it wasn't so happy. Requested access to the resource is denied. So that's the error we got. Since this is access denied right now then I need to login. And if you think about it, anyone trying to access or push images in your repo, they should be logged in. They should have permissions, right? Otherwise, each one will be able to push into every other one's repositories and it's going to be a mess. So, we need to login in order to be able to do that. So, I'm going to do docker login. I can do minus u and I can put here lab user 701. Now it needs the password. Login succeeded which means I should be able to push without any problems now. So now it's preparing things are being transferred and all right. So it looks like we have an image that was pushed successfully. And if we go here and we click on this, we should see version one here. And it's less than a minute ago. If I click on the version on the tag, this is the Docker file. This is the original one before we made that change. And that's why the command is the original one as well. If I go back and if I want to pull this one, then I should be able to pull it using this command, which is great. So now we have the image and it is pushed into the repo and the repo is a public one as we mentioned before. Okay, that's good. Clear Docker images again. Let's push the second one, the version two. So we're going to repeat docker push. Now it's going to be version two. And that's the only change. If you look here, it's exactly the same, but this is version two. So let me push this one. And notice what will happen. Layer already exists. layer already exists. Layer already exists. So many of the layers were in common, right? Because we only changed the command. Everything else is the same. And that's why the layer exists. So it doesn't have to be uploaded again. So now we should see two images in Docker Hub, two versions or two tags. And as you can see, version two, it has its own command. And version one, it has its own pull command as well. And if you look here, you'll find that there is a digest and this is the OS architecture. That means this is for Linux and that's the digest. This is usually unique for every single upload. So even if you keep version two and now we do another push as version two, there will be a second and a third and a fourth digest or it could be one for Windows, one for Linux and so on. So there could be multiple digests referring to the same tag. If you want a specific one of the uploads, then you have to use the digest and not the tag. All right. So now we have version one and version two, which is great. Let's look at version two and see if it has any changes. And as you can see here, command is echo. This is app one. Let me check. Nano docker file. So this is not showing completely in here. Okay. Here, here it is showing complete. All right, great. So, I have version one, I have version two, and life is good so far. Now, let's go over the Docker networking. When you create containers, how can they communicate and how can they communicate to the outside world and how can they be available to communicate with from the outside, from external networks, from the internet. So, this will be covered in this section. Let's start with an overview. Take a step back and let's talk about a network device called a bridge. What is a network network bridge? This is not about Docker. This is generally speaking from the networking space from the networking domain. A bridge is a data link layer or OSI layer to physical or virtual device. What is the data link layer? On the OSI layer, we have seven layers. The first one is the cabling and electrical signals. The second one is about the network interfaces, the Ethernet connectivity and so on. And then layer three is about the IP addresses. Layer four is about the ports and so on. So I don't want to get into that. It is a device that does not understand IP addresses basically and it can connect multiple network segments together. So if I have PCs or clients on segment one and I have clients on segment two, they could be PCs, they could be servers that this could be the data center for example and I would like to allow communication from this side to this side. And when I'm talking about segments, I'm talking about separate networking segments between the two. So the bridge allows the communication from one side to the other. So PC2 and PC3 can communicate without issues. PC1 and PC4 can communicate without issues. PC5 and PC6 they can communicate without issues. That's logically what a bridge is. Now how does it look like? All of us we have a form of a bridge in our homes. If you have internet connection in your home there will be a small device. They call it the router sometimes. But if you go to that device, you will see in the back side that it has ports like this. And the ports connect you using what we call RG45 connectors. So these connectors are the male connectors and this is the female connector. It latches inside and then the little latch here will clip in this place and that's how it gets fixed in in uh place. How can a PC connect to a network device whether it is a bridge or a switch or even a hub? Then that cable connects on one side to the device and on the other side it connects in the PC or the server or so on. So that's how connectivity happens and each one of these ports is called an Ethernet port. What is Ethernet? It's a standard protocol for OSI layer 2. You don't need to understand more than this for now. Just remember that Ethernet is an interface on the network device and an interface on the neck card or the network interface card on the PC or the server or the device connected to that bridge or switch. So this is in layman terms very basic what a bridge is. Why did we bring this into the discussion? Because docker inside the host it builds software bridges virtual bridges. Remember in this slide we said it can be a physical or a virtual device and that's why docker will establish the virtual device inside the docker host and that is a bridge network which is a software bridge to allow containers connected to that bridge to communicate with one another inside the host by default when we start docker inside a host a bridge network called docker zero So a software bridge with the name docker zero is created automatically. So you don't have to create it. It comes with docker by default. And any container that will be created by default will connect into docker zero. And there will be a virtual Ethernet port that will be created here on the bridge to connect the container. We'll discuss this in more detail as we move forward. So is it only a bridge that can allow networking within a host? In Docker, we have what we call network drivers or network modes. So Docker network modes include many different types of networking that you can do inside the Docker host and that includes bridge which is the default network driver or the default network mode. Then we have host. The host basically will have the containers follow the host IP stack. So they don't have their own IP addresses. They are just as if they are extension to the docker host. We'll talk about that in detail as well later on. And then we have none no networking whatsoever. The container inside the host cannot communicate with anything outside cannot communicate with the other containers and the outside or the external networks cannot communicate to the container. Also we will detail that. Then we have overlay. Remember that the bridge and the host this we are talking about networking inside a docker host. What if I have containers in another host and I would like to connect the two together. Then in that case you need the overlay network which can connect multiple docker demons together. This is far from our scope so we're not going to cover that. Then we have IP VLAN networks which provides full control over the IPv4 and IPv6 addressing. Then we have the MAC VLAN which will assign MAC addresses to containers. Layer 2 OSI layer 2 addresses are called MAC addresses. This is part of Ethernet that we mentioned. And then userdeed building custom networks and we are going to look at this one as well. We're going to build custom bridge networks as we work through the hands-on labs. All right. Now let's dive into the docker bridge mode. The very first one, the default one, the docker bridge mode or it's called the docker bridge driver. So containers connected to the same bridge network can communicate. So by default you have the docker host and it creates docker zero by default. We said as soon as you start docker there will be a docker zero bridge. Then containers that you create and you leave them to the default networking settings are going to be on the same bridge and they should be able to communicate with one another. A bridge network isolates the containers from other containers on other bridges. So what if I create a custom bridge, let's say bridge one, and then I have container three and four on bridge one. Can the ones on docker zero and the ones on bridge one communicate? The answer is no. Each bridge will not allow by default communication to the other bridges. Bridge networks apply within the same docker host only. What we have now we are focused on bridge mode. Bridge driver. So in bridge mode and bridge driver a bridge is within the host only cannot extend to other hosts. A container can connect to multiple bridge networks at the same time. And we are going to demo that as we look into the hands-on labs. So if I have container two and it needs communication with container three and container four, I can have a second connection to the container. So there will be a Ethernet port or a virtual Ethernet port here created for container 2 and there was already one here created on docker zero for container 2 as well. container 2 as soon as it connects to both bridges it will be able to communicate with one with three and with four and we're going to de demo that in the lab. So let's dive a little deeper into the networking in docker zero or the default networking that happens on any docker host. So the default docker bridge network it's called docker zero and the IP subnet the block of IP addresses from which the containers that we create and that will be connected to this bridge will be assigned IP addresses is by default 172700 16. So SL16 means this is the range from which unique IP addresses will be assigned one pair container that gets created on the bridge or gets connected to the bridge. All right, no worries. So we have docker zero and we have 17270016 as the range of or the block of IP addresses. The very first IP address in that block is going to be the IP default gateway between the bridge docker zero and the docker host. So this connection between docker zero and the docker host it passes by the IP address which is the IP default gateway 17270.1 and this does some routing function. So it can connect discrete networks. This is arranged different than what is on the host. So how can they communicate? There has to be some routing that is happened on that gateway part of docker zero. When we create a container unless we specify otherwise then every new container will be connected to docker zero. Any container that you create will be connected to docker zero. But how would that connection happen? The connection will happen between an Ethernet zero interface software interface virtual that will be created on the container and a virtual Ethernet interface that will be created on the bridge. And this is a logical a software binding between the two as if it was the cable that we were talking about in the previous video. Each container created in bridge mode has an Ethernet zero as we mentioned and the IP address gets assigned to it. So each container gets a unique host IP address from this range without duplicating what we have used before. So number one or.1 is the gateway. The very first container created will be two. The second will be three. The third will be four and so on. So unique IP addresses and we have a large pool from which we can pick a unique unused IP address and assign it to a new container. And virtual Ethernet interfaces are exactly virtual version of the physical ports that are on the physical bridges. So you can think of what is a virtual interface. This is exactly as if it was a physical one but this is in software. So that's the meaning of a virtual interface. An interface that cannot be touched. It's only software and we cannot hold it or we cannot connect a cable into it. And this binding that happens is also software binding between Ethernet and the virtual Ethernet interface that is on the bridge. So the Ethernet gets created in the container and the virtual Ethernet on the bridge and the binding between the two is as if we have a cable connected between them. All right, that's fine. So the question now we are still in the default bridge mode, the default networking mode in Docker. When I create a container and I don't specify anything for the networking as we mentioned there will be an Ethernet interface an IP address from the default range will get assigned and a virtual Ethernet interface will be created on the bridge and binding will happen between the two. All right. So the question is if I have external networks the host can reach these external networks. Let's say these are on the internet websites or whatever on the internet. Would the container in the default bridge mode be able to access the external sites? So for example, would the container be a able to ping the 8.8.8.8 IP address which is the Google DNS. Would it be able to do this? If the host can do it, would the container be able to do it? And the answer is absolutely yes. Outbound connectivity. We call this outbound. Outbound means it's coming from here initiated and it's going out to the external networks. So it's going out of the container. It reaches the host through the IP gateway gets to the interface Ethernet zero of the docker host and then it will route it outside. Now the question is if this is on the internet but this is a private IP address. a private IP address cannot be seen on the internet. Then how can this be masked such that the internet will see that this is coming from somewhere on the internet and then when the response comes back then this will be reversed again and it will be sent to the right container and the answer is network address translation. the host will perform network address translation as that traffic is coming out and when the response comes back and it looks like this. So let's say the docker container would like to communicate with the outside 8.8.8.8. So the packet or the message is going to be sent out and the source is 172.17.0.2. This is the sender and the destination is 8.8.8 8.8 as it travels through docker zero and the IP gateway and it gets to the host the docker docker software itself will find out okay hold on hold on this is going to the internet and it is going out of my controlled area which is the docker controlled area the IP addresses here are private and they are not known to the outside so what I need to do is I need to strip the source IP address from the message and I'm going to add of course it works with the host on this and it's going to add the IP address of the host as if the message is actually coming out from the host and now if this is a private IP address then the host or the network that the host is connected to if this is AWS cloud the AWS cloud is going to also do network address translation and hide that behind the public IP address reachable from the internet. So the docker host is going to translate that the message was from this source. It would now assume or the message that will come out of the host will have a source address that is the host IP address. So the source address will be the host IP address. When the traffic comes back the source will be 8.8.8.8 8 and the destination will be the IP address of the host. So when it comes back then the host will realize who talked to 8.8.8.8 and it will find out this was the container and that's how the destination will be changed from this IP address to the container IP address. Okay. So that's called network address translation and the docker host will maintain the net entries in IP tables. Okay. So if you want to think about that, if you don't have an idea about it, let's say that my name is Issa and there is and your name is George and I would like to talk to you. However, I'm not allowed to talk to you directly because I have a functionality or a function inside that office and I should not be able to talk to the client directly. But there is a mediator called Joan and Joan can talk to George and can talk to me. So if I need to talk to you George, I'm going to talk to John. John, can you please get this message to George? So we have here Issa and we have John and we have George. Issa would like to talk to George directly but this is not possible. So what Issa will do is Issa is going to give the message the envelope if you will to John and would say John this is going to George. So what John will do because we don't want anyone to know that Issa is speaking to George and they are not allowed to speak to each other directly. So what we'll do is John now is going to change the envelope and we'll write on the outside that this is coming from John where in fact this was coming from Issa not from John and it was going to George through Joan now it will be from Joan to George that's exactly what happens but Joan because he's doing the same to Isa and to Ahmed and to Ram and to other people John is going to maintain a table and would say okay I know that Issa was talking to George and maybe Ahmed was talking to Ram and then maybe Krishna was talking to Sara. So he will maintain this table. Now when the response comes back from George doesn't know about Asa. So what will George do? He will say okay here is the response John. So we'll give John the response. John is going to look at this table and would say who was speaking to George? Oh, that was Issa. So, it will send the response back to Issa. So, that's exactly what happens, but instead of names, these are IP addresses. All right. Hopefully, this is clear and we are going to look at that in the table. Now, bridge mode. Can I have multiple bridge networks inside a Docker host? And the answer is yes, absolutely. We have the userdefined or the custom networks and you can build your own if you would like to. So they can coexist inside a docker host. But of course there has to be a reason for that. It's not just creating networks to be cool. So by default let's say we have app one containers and they are going to be on docker zero. Here is the range and this is the IP address assigned to the container and this is the bridge gateway or the IP gateway.1. and this is the Ethernet and this is the IP address of the docker host and the docker host is connected to the external networks. Now if I bring in another network then there will be a new bridge different bridge and then containers connected to that bridge are going to also have a different range and they will have different IP addresses. So if this was for a database or application 2 or anything and we created a custom network bridge one for example when you create a custom network it will not get the same default range it will get an other range and you can specify a range other than the 172 if you would like to. So it can be 10.0 and we'll see that in the lab. Now you connect the containers and virtual interfaces will be connected on bridge zero for the containers that will be attached by default to docker zero. And if you specify for app to container that you need to connect to bridge one when you are creating it then it will get an IP address but from a different range which is the range of bridge one. So this is possible and containers are going to have outbound access and also Ethernet zero or the host is going to maintain a table of who is talking to whom. So when the response comes back then the translation of addresses can happen without any problems. So we can create custom bridge networks as needed aside from the default bridge. So this one will be created anyways as soon as we start Docker but you can build others other networks if you'd like to. Please remember that by default bridges isolate their containers from all other containers. They cannot communicate. So this one and this one by default they will not be able to communicate. So let's now cover some of the docker networking commands that will come in handy when you are dealing with docker networking. A Linux command at the beginning is very crucial which is the IP address command or the IPA. The very first command we are going to use is IPA. very important command that we use on the host and inside the container when we are inside a shell in the container to find out information about the available network interfaces and if they have associated IP addresses on a Linuxbased system if this utility is not available in your container you can install it using the IP route 2 utility and we will see that in the lab now what if I need to find out on my docker host what are the available networks docker networks So I can use docker networks ls and that will list all the available docker networks docker networks create and then the name this is if you would like to create a custom network in docker so this was going to create a network with a specific name if you did not specify the subnet or the IP range then it's going to to take the next available 172 range if this was the first custom network, it will take the 172.18. If it was the second one, it will take 172.19 and so on. What if I don't want a default IP subnet range for the network and I would like to specify my own? Then you can do docker network create hyphen subnet and then the subnet range you would like to use and then the name of the custom network. What if I need to inspect one of the networks and I would like to find out which containers are on this network and what are the IP addresses they are assigned to, what's the range of the network and so on. So a lot of details about one of the networks whether it is docker zero or one of the custom networks then you can use the command docker network inspect not docker inspect network docker network inspect and the name of the network or the ID of the network. If you want to create a container using docker run, but you would like this container not to be connected to the default docker bridge which is docker zero. You want it to be connected to bridge one or application such and such network. Then you can when you are creating the docker run you can use hyphen network and the name of the network and then the image. And of course you can combine that with hyphen it and hyphen d and hyphen all the hyphens that we have seen before and the hyphen p to publish ports and so on. So this will run a new container and connect it to a docker network that you have specified here. You can also do for an existing container that is not connected to a custom network. So let's say I created a container. The container by default is in docker zero. Later on we created a new network. Let's say it's called bridge one. And now I would like to connect that container that was only connected to docker zero to also have a connection into bridge one. What do I do? In that case you can do docker network connect the name of the network and then the name of the container. The network is first and then the container comes second. Not the other way around. So we did the testing we wanted and for whatever reason now I need to disconnect the container from bridge one again. Then you can use the command docker network disconnect the name of the network and the container name or the container ID. All right. So now let's look at the bridge mode in the docker networking modes or networking drivers. Let's go ahead and look at that. So I have the docker host and it's running right now. So I'm going to do connect and I'm going to open two terminals as we are used to. So again connect and again another terminal and then in each one of them I'm going to do the normal sudo su and then clear. So now we are inside the host as the root in terms of privileges and clear again. So what I need to do is I need to create a container and I need to get into that container and check outbound connectivity. Does a container by default has outbound access to the internet? And the reason why the container has access to the internet is because the docker host the EC2 instance has public IP address and it is launched on a public subnet. So it can access the internet. So if the host can access the internet, can the container access the internet? That's what we'll investigate right now. Let's do docker images. And this image I created from Ubuntu and it does have the utilities installed. Usually the Ubuntu does not have the curl and ping and IPA and all that. So this one has it. So I'm going to launch a container from this image docker run. And I'm going to do minus it. I need to get into the container and I'm going to assign the name p test and it is from this image and the version is 1.1 and I'm going to run bash. So now I'm inside the container. Here's the container ID. If I do pwd I am at the root and what I will do right now is I want to do ping 8.8.8.8 which is the Google DNS. As you can see we are getting a response which means the container has access to the outside world. Remember that the container will have an IP address. Let's investigate that. So let's do IPA or IP address. So we did IP address or IPA. If you do IPA, you'll get exactly the same output. So what is the output? Here's the command. Let's look at what is this. This is the loop back interface. So any container whether it has connectivity and in networking or not will have a loop back interface an internal interface. Don't worry about that. The most important one is this one Ethernet zero. Remember we said that any container that is established or created will have an Ethernet interface and it's always in Ethernet zero for the first one. The second one will be Ethernet one and so on. So look here what do we see here? We see that it had received an IP address 172.17.0.216. Remember when we were talking about the fact that the range by default for the docker bridge is 1727006 and.1 is the IP gateway. This is now the container and that's the IP address that it has and this is Ethernet zero as we mentioned. So this is on so this is on the container. What is going on on the other side which is the host? Let's check. Let's do IPA. And if you look here, we have the loop back as well. Then we have this one which is from AWS. And that's the private IP address of the virtual instance, the Docker host or the EC2 instance. How do I know this? If you look at this number and you look at this number, it's exactly the same. 1723145181 and it's exactly the same. So this is the private IP address of the Docker host. Right now again what else do we see? We see docker zero. So docker zero is the default bridge. And for docker zero here what we have is we have an inter internet interface 1727016. Remember what that was? This exactly this was the the IP gateway of the docker bridge. So the interface docker zero is on the default bridge and the default bridge is docker zero and it has an IP gateway or an IP address interface and it has an IP address and that's how the host communicates with the docker engine or the docker uh bridge. Then we have virtual Ethernet. Remember when we said that every container that you create will have Ethernet zero on the container side and will have a virtual Ethernet interface on the bridge side. So this is V8 or V virtual Ethernet 8. It's up and it is on docker zero. So it is on the bridge. So this proves that it is on the bridge. And this is the IPv6 interface. The inet 6 is for IPv6. So you're not only getting an IPv4 but there is an IPv6 also or the subnet scope link that is available on the bridge side. So now you have all of this which proves what we have said in the theory and that is how the container was able to access the outbound. Now how can we confirm that this belongs or this is connected to the container? Very easy. Let's go here and let me do exit. And when I do exit, let me do docker ps. There are no active containers. ps minus a. I will find the container that we have created. Here is the name and it is exited. Now let's go ahead here again and let me repeat repeat the same command. You will not find the virtual ethernet. So I have the one which is the private IP from AWS. I have the docker zero did not change but I don't have the virtual Ethernet. So with virtual Ethernet interfaces on the bridge side they are created and terminated. When you create the container they are created. When they are terminate the container or exit the container they are exited as well or they are terminated as well. All right. So let's now clear and let me do the so let's do the bridge mode in docker networking and let's do a deep dive. So let's do docker network ls list the existing networks and look at what we will see now. So I did not create anyone. These are all defaults. So I have this network ID. The name is bridge and the driver is bridge and it is local. Then I have this one and the type or the name is host. The driver is host. So it is from the docker networking host type and it is local. And then we have none and the driver is null and that's local. So I have three networks available on the docker host by default. That's what we have right now. All right. So let me do a clear now. And what we will do now is let's create a container. Docker run fy- it. The name is container one. The image is engine x. And I'm going to run a shell inside. And I have the interactive /bin /bash and I have the interactive here. So this will keep the container up and running. So I'm inside the container right now. As you can see, if I do IPA, you'll find that the command is not found. So what do we do if you wanted to install this? If I want to confirm whether it exists or not, if I want to confirm, I will do IP address. Do I have this? If you don't get any response that means engine X by default it doesn't have the IPA address. Okay. So let me do ping 8.8.8.8 again command is not found which ping. So do you have it installed? No I don't have it. If you want to confirm then let's do ls and you'll find that ls exists and here is the path. So the packages or the tools or the commands that are available on the image you will find that it will respond with a path. If it doesn't exist then it will be just quite silent. So what do I do now? You can do apt get update. So now I'm updating the image and then I will do apt get install minus y. If you want the ping then it is IP utils/ping. And now it will install ping. Now let's clear and let me do ping 8.8.8.8. You'll find that it is responding now. So it has been installed. And if I do which ping you'll find that there is a path to it. So now it is installed. So don't be afraid or panic when you don't when you try to do these commands and they don't exist. That means the package is not installed. That's all. If I do IP address now it's not available. So what I will do is app get install minus Y and then I will do IP root 2 and this will install many things including IPA. So if I do IPA now you'll find that the response is not it's not found. It's it is found now and it has responded. And if I do which IP address then it will tell me that there is a path to it. All right. So I have it available now. So we have an IP address on the container. Notice that since we stopped the first container now the second one we created it took the same or the first available IP address which is2. That means a stopped container kind of loses its IP address. Okay. So let me go on the other terminal. I'll keep this one up and running and I will go on the other one and I'm going to do docker network inspect. I want to inspect the network that is with this ID the bridge one. Let's look at what information we have when we do this. So the name is bridge and here is an ID and it has been created on such and such date. The driver is bridge. So it tells you what the mode is. Then here is the subnet for the configuration. This is the subnet. These are all defaults. So it confirms what we said before. And this is the IP gateway. Then we have here as you can say containers. I have one container running with the name cont one container one and the MAC address the layer 2 address and the IP address are available here as well and it is docker zero. So got so we get a lot of information about the network and its details and also the running containers. So let's do this. Let me just go here and do exit. So when I do exit what will happen? Yes, the container will stop. So docker ps minus a I have two containers stopped and container one is included as well. Now if I go back here and I run the same command again and we get the output you'll find that now so if we inspect the network again you'll find that we don't have any containers available. It might take a couple of seconds between the time you stop the container and the IP address to be revoked but now I don't have any running containers as you see here. When we create an application that is going to have containers, that application is going to have data. So it could be files that the application is going to create. It could be that database or the data in a database if that container was about a database. So how can we keep that? How can we maintain it even if we restart the container or we kill the container or we delete the container? That data could be critical and we would like to maintain it. And that is what is data persistence all about. How can I make sure that my data is going to survive a container delete or a container hang or any issues with a container? That is what we are going to discuss in this section. So why do we need to persist the data in Docker? As I just mentioned, because if you have a container with data and the container is deleted or is killed or it stops or whatever the problem happens with the container, I'm going to lose my data. Think of a MySQL database for example or critical data files or information or session data even that you are using and then the container disappears all of a sudden and all the data is gone. How can you recover it? That is what we are going to discuss now. The benefits of persisting data in Docker are many and the least is database files logs and all that we would like to maintain them. That's the number one benefit. And then we can also share data between containers. Let's say it is the website data, the index.html and the other HTML files. Now if I run a container, it will tap into these files. If I run 10 containers, I don't want each of them to have a copy of that on itself. Why don't they access a common or shared data in a volume or in a storage that is independent of the container itself? Also we can use it to separate application code from user data. So we don't have to store the database data for example on the container with the database engine itself or if it is an application related data I don't want it to be with the code on the same container. Avoid losing data when a container stops or is deleted. There are two common ways to persist data in docker. The first one is called named Docker volumes or they could be anonymous docker volumes. So docker will create random names for the volumes. That is one thing. And then the other way is we can have folders on the host and these are going to be where the containers are going to save their data and they are called bind mounts or bind mounting. The difference between the two is when you create Docker volumes or name Docker volumes, they're going to be on directories in the host in an area on the host that is completely controlled by Docker. Bind mounts. They are folders or directories on the Docker host, but they are not controlled by Docker. They are on the host file system. So, this is the main difference and we're going to look at them and when to use each. Let's now discuss the first type of persisting data solutions in docker which is the named docker volumes or sometimes called the docker volumes. Volumes are going to be in the host file system. So if this is the docker host the green rectangle in the host file system there is an area controlled by docker and the volume when we do the named volumes storage to persist data then it's going to be somewhere in the docker area. So where in the docker area where in the file system as we mentioned early on that if you have a normal installation default installation path for docker on Linux system or Mac OS not on a virtual machine on Windows or your laptop then the default path is going to be v/b/doccker and then we will have a directory called volumes and this will be the volume name. So this is let's say you create a volume called volume one this is going to be volume one folder and then underscore data and anything that has to do with this volume is going to be stored under this subfolder. So if I have multiple volumes they will share this common start path and then it will be volume one volume 2 volume 3 demo volume data volume and so on. And as this shows that when we have a volume that we are going to mount with a container, the storage in that volume path is going to be into the storage volume on the host. So even if we lose the container, the data is going to be in a volume on the host, not in the container itself. And here's the path var docker volumes. And then the name of the volume, the volume name and underscore data. And we can have multiple containers mount that volume. It's not a single container volume. The Docker volume is isolated from container layers. So when you write to it, you're not writing to the file system of the container. It will persist independent of the container. So even if the container is deleted, the data is still there because it's on the host. And it is mounted into containers at run time, not after. And it allows data to survive container restarts, deletions, and image rebuilds. All of that the data is going to be on the host. But of course, if you lose the host, then you have a problem because the host will take out all the containers and all the volumes and all the data in the volumes as well. We are still talking about Docker in a single host. We did not get into the swarm docker swarm part where we can orchestrate or can create containers on multiple hosts. Docker volume commands. How can I use commands to create and to mount Docker volumes and so on? So if you want to create a named Docker volume, you can do Docker volume create and the volume name that you specify or that you prefer to have. You can list the available Docker volumes using the Docker volume ls command. And you can inspect and get a lot more details about a docker volume when you do the docker volume inspect and the volume name. And you can also delete a docker volume using the rm or remove and a volume name. So docker volume remove or rm when you want to mount an existing docker volume when you are creating a container using the docker run command. How can you do it? This is what we are going to look at right now. So the option in the docker run command that you can use to mount a volume is hyphen v and then you have the volume name that you have created column and then the path or the directory in the container where that volume is going to be mounted. So this is to launch a container with a volume attached. But of course you need to have the docker run command before that. Here's an example. docker run minus v hyphen v my data. So we have a volume with the name my data and it's going to be mounted at the app data directory in the container and the image is Ubuntu. So inside the container if I go into the app data folder and I write anything or save anything this is going to be in the volume that is on the docker host. It's not going to be in the container file system. So you are writing as if it is in the containeriz file system but that goes automatically into the volume on the docker host. We can also provide a read only access for a container to a volume. So if I do the docker run hyphen v the volume name and the container path and colon ro that means read only. So give the container read only access to this volume. It cannot save files and it cannot edit what is on the volume. And here's an example. Docker run-v my data. So this is the name of the volume and the path inside the container is app/d data and then it is read only from an Ubuntu image. We can share or have multiple containers use the same Docker volume. And it's up to you where you want to mount the volume inside the file system in each container. So more than one container can share the same volume and they can have access to the data in the volume. If you have a container and you'd like the container to inherit or have all the mounting all the volumes that are in another container, you can also use it with a docker run hyphen volumes from flag which will allow one container that you are creating to have all the volume mounts from another container. It's not as common to use. However, it's a feature that's available. So if you do volumes from container one that means the new container is going to take that volume mounts from container one into container 2. So this is going to be preceded with docker run and the name of the container is container 2 and then hyphen hyphen volumes from container one. So you're not specifying the single volume mount. You are mounting whatever is on container one in container two. And here's a full example docker run interactive uh session hyphen volumes from container one Ubuntu. So this is going to have that the it or you can hear run bash for example. This is not showing here. So you can get into that container command line but also you'll get all the volumes from container main. Let's go ahead and play with the named Docker volumes. The first type of persisting data in Docker. So, let's open two sessions to the Docker host as we always do. I'm going to open a second one. Connect. And then connect. I'm going to do sudo su and clear. And here I'll do the same. Okay. So, what do we need to do now? I need to create a docker volume and then we are going to create a container and mount this volume to it and then we are going to get into the container write some text using a echo command into a file and then we are going to exit from the container the container will be removed I'm going to use the docker run hyphen rm which means as soon as you exit from the container from the interactive shell it The container is going to be deleted completely deleted. So it will not even show in the docker ps minus a. And after doing this we are going to create another container and then we are going to mount the same volume to it. And then we are going to ls get inside the container and find out if we have the same data available or not. Then the second container also would be created with a minus minus or hyphen rm which means remove as soon as it's exited. We'll exit from the second container and then we're going to do a cat to the path in the docker area where the volume is and see if we have that data or not. So that's what we are going to do right now. And this will prove despite the fact that the first container was deleted when we launched the second container and mounted the same volume the data was still there which means it is not in the container that was deleted. And when the second container gets deleted, we do the cat to the path in the host and we'll still find that the data is there, which means the data persist irrespective of the life of the containers. So let's go ahead and do this. Okay, so here's what we're going to do. Let's go ahead and check if we have any Docker volumes available beforehand. And we don't have any. Let's go ahead and create our first named Docker volume. So, docker volume create and I'm going to call it volume one. If we do the same command ls again, it should show me volume one. I can do docker inspect volume one. And as you can see when it was created and it's local and here is the mount point where this volume is mounted and the name is volume one. I'm going to look at this path because it's very important. /bar /bdoccker this is the docker controlled area it has a subdirectory called volumes and I have a volume called volume one under that and then a subdirectory underscore data and then any data I'm going to save in that volume from the container it's going to happen under the /data subdirectory so I'm going to copy this because I'm going to use it shortly all right let me clear okay let's go ahead now and run a container And this will be used docker run and then minus rm or minus minus rm. Delete the container as soon as it job is finished or as soon as you exit from the container. And then I need to mount the volume one and this will be mounted at the / data directory on the container. I'm going to create it from an Ubuntu image and I'm going to execute the command or this is the command that the container will execute. bash minus C treat anything between the strings as a command echo and then I'm going to echo hello from docker volumes and this will be redirected under data under a file called hello.ext. So basically create a file called hello.ext text under the folder data which means it will be created on the volume if what we are saying is true and the container will execute this and the content of the hello text will be this text and that is going to be under the SL data directory which means it will be in volume one so let's go ahead and do this and find out what's going on I did not close the code so let me repeat the command again and let's close the code because we have a quote here it has to close and and let me hit enter now. All right. So let's do docker ps minus a. I don't see any containers because this instructs to delete the container. So the best way to find out is if we cat and then var li do docker volumes volume one data and hello.ext. So this confirms that this file has been created. under var lib docker which is the docker storage area and then volumes volume one data and there is a file and how do I know because here is the output which is exactly what we have instructed it to do right here okay so the container disappeared deleted but the data is still there now can I use that on a different container let's find out so let me repeat the long command again but we don't need all of is right. So I'm going to go here and I'm going to get into the container /it and it's going to be a bash and created from Ubuntu. So now I'm inside the container. Let's do ls and I have a data folder here as you can see. So let's see let's do cd data and ls. I have the hello.ext text which was from the previous container made by the previous container but the container is gone but the data persisted the data is still there and if I do get kh hello text this proves that the volumes persist even if the container is completely deleted right I think it's clear and let's go ahead and now extend this and look at volumes when two containers are live and they are saving files and what happens on the other container. So let's go ahead and do this right now. So let me exit from this one. If I do docker ps, I shouldn't see any because we used a hyphen rm and I don't have any. And I am done with the volume. So let's go ahead and also remove volume one. And if I do docker volumes ls, I shouldn't see any. Okay, let's clear. Now what do we need to do? I need to create two containers and I'm going to mount the same volume volume two on both containers and I'm going to get into one container create a file on that directory for the volume and then get into the second one and check if I can see that file from container one. Then I will create a file from container two and then go to container one and see if it can see that file or not. So by doing this that means visibility of the data shared in the volume is going to be across the containers that have this volume mounted onto them and they will have read and write access to the volume unless if I choose to provide them only read only access and this is what we are going to end the lab with a third container with readon access to the volume. All right. So, I'm going to do docker volume create and I'm going to create volume 2 this time. And if I do docker volume ls, I have it. And do docker volume inspect volume 2. And here is my volume. That's all good right now. Okay. Let me clear. And I'm going to create now container one on this side. So, docker run hyphen it I want to have interactive shell into the container and I'm going to have volume 2 mounted into the let's say folder one inside the first container and this is going to be an Ubuntu container and I'm going to run a bash shell into it. So now we are into the first container. Let me go to the other side and I'm going to use the same command but let's do folder two on this container and I'm now inside the second container. Let me do ls and you'll find folder two here. So if I want to save anything to the volume I need to write it to folder two. So let's move into folder 2 and do all my work here. So I'm going to echo hello from container 2. And I'm going to redirect that to container2.ext ls. And if I c the file cont 2.ext, I should see what I have just typed. All right. So let's take this command now. And I'm going to go to the first container and I'm going to do the same thing. LS and I have here folder one. I'm going to go into folder one and I'm going to use this command but I'm going to to say this is container one.ext and hello from container one. And if I do ls as you can see I have access to container 2 file and container one file. How? because you are writing in the folder that maps to the volume. So everything you are actually saving goes into the volume and that data will persist even if the two containers are gone. So let's cat from here count2.ext to check and yes that's true. And if I cat one text now if I go in the other one and I do ls again now I can see two files. So read write access to both of them. Now let's do one thing. Let me open a third terminal and I need to inspect these containers and find out the mount path if they have any reference to the volume attached to them and where it is mounted. So I'm going to do sudo su clear. Let's do docker ps minus a. So I have these two containers. I would like to inspect each one of them. So, I'm going to do docker inspect for the first container. And if we go up until we found the mounts here, mounts, you'll find that there is a volume mounted. The name is volume 2. And here is the source or the path to where the data is saved. And it is mounted to folder two. So this is where the volume is that is mounted or mapped into this destination folder 2. That is container 2. How did I find out? It's folder two. Now let's do the same for the other container. So let me docker ps again. And I'm going to use the same thing, same command. And then the second container. And if we go up again to the mounts, you'll find that it is mapped into folder one. So this is container one. So this is in the container and that is the source on the host and it is volume two. So it's very clear that how the mounting works and also we have proven using different containers that they can share the data on the volume and they can both mount the volume at the same time. Right? Let me now demonstrate how we can do the read only option. So let's go on the home again and let's do a docker run and I'm going also to use it and this is going to be also mounting volume 2 at the let me call it folder three because this is container 3 and this is going to be read only. This is from Ubuntu image and it's going to run a bash command. Let's go ahead and look at this and let me ls cd folder 3 which is right here in to get into the container or the volume and be able to read and write. If I do ls I can look at container one and container two. Can I cut their content? Let's find out. Container one.ext or container 2.ext. Yes, I can look at it. And then how about container one.ext? I can look at it as well. Now, can I create a directory in this volume? And this is a right action. So, let me see if I can do make directory. And I'm going to call it nano test. You'll get an error. Cannot create directory. You have only read access to the file system. So, that proves that I can read. I cannot delete. Can I do remove container one text? Let's see. I can't because it's read only access to the file system. One last thing that we would like to see is how would the mounting for this container is going to look like compared to the others. So in order to do that again I'm going to open a new connection to the host because I want them all to be running. I don't want to disconnect any one of them. And let's do sudo su. And I'm going to do docker ps. And I have three containers running. And I'm going to look at the one the most recent one. And this is container 3. So let's do this docker inspect this container. And if you look at the mount, you'll find something different here. See here read the read is false. So this is on folder three, the same volume. The source is the same volume, volume two. And this is folder three on container three. But you'll see here that the read write is false. So it has only read only. Whereas if I do the same but for the other containers. So let's just pick one of them because they're going to be the same. Let me take this one and I'm going to repeat the command. Let me remove this and replace it with the ID that ends with 7 E6 for the second one. And if you hit enter and you look at the mount, you'll find that the mount in this case, I think I skipped it. It should be here. Yeah, here you'll find that read write is true. So if you did not specify the read only option when you are doing the volume mapping between the volume and the path in the container. If you don't do the column read only by default it's read write but if you do it then it's read only and then you have seen how it behaves. The second type or solution to persist data in docker is called docker bind mount or docker bind mounting. If you hear either of them, this is exactly the same thing. And sometimes it's also called the host path. So what's the story behind this solution? In the docker volume or the named docker volumes, we have discussed that a container with a volume, the volume is going to be in the docker controlled area or the storage controlled area managed by docker. It's going to be a subdirectory in there and the container anything written let's say if the volume was mapped to the / app directory in the container anything written into the container is going to be actually written into the directory for the volume and anything available in the volume will be visible from the container at least at the read only if this is how the mounting happened or it could be readr so the container can change can add can delete can can manage manage or modify the contents of the volume. So bind mounting on the other hand is simply we are linking or mapping or mounting a host path a directory on the host file system away from the docker area. So somewhere outside so it could be anywhere outside the docker area we mount that or it could be a file to a container path or file. So you mount directory to directory or file to a file. The bind mount or the bind mounting may be stored anywhere in the host file system. It's not only restricted to the docker storage area. And bind mounting is used with docker run commands and not in a docker file. So we cannot do the mounting as of now in a docker file. Bind mounts they are different than named Docker volumes because they are perfect for development and testing. In this solution if we would like to change the volume it is highly not recommended to touch it from the file system. So you need to initiate a container mount the volume and then delete or add or change files in the volume and then you can mount the volume into other containers and use it. Whereas in the bind mount, let's say this is the file or the path on the host that we are mounting or mapping into the container. Now any change you can do on the host because this is on the host. It's up to me. I can add files. I can add HTML files. I can add whatever I like. And any changes you do here, it will immediately reflect in the container. So for development and testing this is more handy than launching a container and then mounting the volume and then changing the content of the volume. So for development and testing this is perfect for production. Go ahead with the named volumes. Can I do the docker bind mounts using the docker run command? And this is an example. docker run hyphen v still like we did hyphen v with the name docker volumes and then the path on the host colon the path on the container. So this path and its content and any changes that happen to it will immediately reflect into this path inside the container and any image engine X my image Ubuntu or whatever the SL app directory in the container will be mapped directly to the host path home user project and we can also do docker run instead of giving a fixed path in the host I can do dollar sign and then parenthesise pwd print the working directory. So where wherever I am when I run the docker run command this directory is going to be mapped to / app in the container that I'm going to create from my dev image or Ubuntu engineext or whatsoever. So anything now I will do on the current working directory is going to immediately reflect in the container that was created. So I could be working on that same directory with VS code or Vim or index html files or anything. And this will be reflected immediately to the container path under the /app folder. Here's an example for this one. And here's one more meaningful example. Docker run-v and then home user engineext.com. So this is a file that is usually available on the engine x file on the host system. So if this was home Ubuntu then this is going to be engineext.com and then it will map into the container under etc engineext engineext.com. So this is a file engineext.com created and what I'm doing right now is I'm mapping this into the etc engineext.com or the default.com or etc xcom.d/default.com. So what I'm doing is whatever changes I make here they are going to reflect into the engine X configuration in the container and the container will be from engine X image. So this is injecting a host specific configuration into the container without having to rebuild the image again. So this is where it comes handy for development and testing. But again it's not the best for production. So which one to use docker volumes or bind mounts? The docker volumes are better for production because of the following reasons. Number one they are in a stored area or a docker storage area controlled by Docker. So they are safer. They are less errorprone. Somebody working in bind mounts on the host file system might by mistake delete the volumes or override their content. They are also portable. There is no hardcoded path in the file system or anything. And they are easier to back up than bind mounts. Also the docker volumes are better integrated with docker tooling. So the different Docker tools, they will integrate better with Docker volumes than with bind mounts. Let's go ahead and play with bind mounts a little bit in order to understand how they work and how we use them. Right? So let's go ahead now and look at how we can persist data in Docker using the bind mount or the bind mounting or the host path. Different names for that. So here is what we are going to do. So we have our Docker host. We are going to create a folder a directory called host hyphen folder and this is going to be the full path. So this is the default path when we get into the docker host and then this is the name of the folder in your case. Please use pwd print working directory to find out where you are exactly and then you will add this part to it. Okay, so we did that. What are we going to do next? We're going to create a file with some data into that directory and then we are going to use this as a volume or a bind mount that is going to be used as the persistent storage for containers. We are going to create and we're going to look at the features. Please remember that this is binding or a host path mapping into a container path. This is not or has nothing to do with the docker area. it is in the host file system and not in the docker area or the docker protected and managed storage area in the host. All right, let's go ahead to the console. So I have multiple terminals open and ready for us to start working on this. So if I do ls, I don't have anything here. So I'm going to create make directory and I'm going to call it hosty folder. I'm going to get into this directory. ls I don't have anything and I'm going to echo and I'm going to say hello this is the host bind mount and this I'm going to direct it into a file called hostext and if I do ls now I have the file as you can see it's right here and if I do cat host.ext to see what's the content. The content is the message that we have written. All right. So that sounds good. What do we need to do now? Let me go back one step. And now I would like to run a container in an interactive mode. And this is going to be named container one. And this will be from an Ubuntu image. And I'm going to run the command bash. So I need to do the bind mount to the container as it gets created. So I'm going to do minus v. And then I would like to know the path. And what I will do is I'm going to take this path because that's the path where I am. In your case, you can do pwd print working directory before you do the docker run. So you'll know exactly where you are. And this is going to map into a folder in the container called container folder. If it doesn't exist, it will be created. And that is Ubuntu bash. And hit enter. And I'm inside the container right now. Let's do ls. As you can see right here, we have the container folder. If I go into the container folder and do ls, you'll find that we have the host.ext text which was on the host path or the host directory and if I do cat for the host.ext text it will be exactly the same. This is the host bind mount. All right. Now let me do echo from this side and I'm going to echo. Hi, this is container one. Copy. And I'm going to append it. If you do two greater than signs, it's going to append. If you do only one, it will overwrite what is in the file. So I'm going to do this for host.ext. Now let's do cat host.ext and you'll find now that there is the original message and the response. If I go on the host now and if I do cat host folder host text you'll find that we have the two messages. So now whatever changes on the container for this file it's going to appear on the host as well. So let's go ahead and do CD host folder and I'm going to do echo I container one nice to see you and I'm going to append this to host.ext again if I do cat host.ext you'll find that we have all the messages and also I'm going to nano host to do text. I'm going to say hi from the host. I'm going to do Ctrl X Y save. If I do ls, now I have the two files. If I do cat host 2.ext, you'll find that hi from the host. If I go back to the container and in the container folder and I do ls, I have two files. I have host.ext and host2.ext. If I cat host.ext, I'll find the message, hi container, we're nice to see you. And if I cat host 2.ext, you'll find the message, hi from the host. So it's very clear why this is favorable because I can change anything on the host directory and it will immediately map or reflect on what the container sees. And if this was configuration, configuration changes, HTML file updates and so on while developing and testing. So this is the easiest way. I don't have to go into creating a new container, mounting the named Docker volume, doing the changes and then create a new container that will use these changes and so on. So this is the easiest. You can just update on the host and it reflects on the container immediately. Now what if I have a second container available created? So let's do also docker run and I'm going to run a different container but it's going to follow the same thing. It's going to mount the same volume and again I'm going to get into an interactive shell bash and it will mount on container folder. If you don't want to confuse them, I could I could say container 2 folder. So you can differentiate between the two and hit enter. So now I'm inside the container. LS I'll find container 2 folder. And as soon as I get into it, I can do ls. And as you can see, we have host two and we have host.ext and they are the same messages. And again I have one container that was communicating with the host and this one also can communicate with the host and say hi this is container 2 anybody there and we're going to append this to host tech or let's let's do it on host 2.ext text. Let's go in the host here and I'm going to go cdhost folder ls and cat host 2.ext. You'll find the message this container to anybody there. So now it's very clear how the different containers can use that host folder and any update you will do it will reflect to all the containers at the same time. All right. Now let's inspect the two containers and see what we have in terms of bind mounts that appear or the mounts that appear in the container. So docker inspect container one if we look at the mount part. So here is the mount and the type is bind. Before in the name docker volumes it was volume. The source here is the path home Ubuntu host folder and destination is container folder. So this is container one and it is read write. If I do the same to container two only difference will be in the folder that we are mapping. So the mount type is bind source the same but here it's a different one and read write as well. If you go up in under the binds, you will find that also there is some host config binds home Ubuntu host folder is mapped to container 2 folder as you can see. So you can look at it at the host config or in the mounts. The mounts will give you the source and destination. But here also it's very clear because the colon separates the source from the destination. So let's now create a third container and we are going to do the bind mount but with read only access and we'll see how it behaves. So I'm going to do docker run minus it and then the name is container 3 and I'm going to do the host path or the bind mount and this will be to this path. So home Ubuntu and then the name is host-en folder and this will mount at the container 3 folder. If the folder does not exist, it will be created read only and this is going to be Ubuntu and the command that will run is bash. Now let me ls and we have container 3 folder as you can see here. If I do cd cont 3 folder and do ls, we have the two files as you can see. If I want to echo as I did with the other containers and say hi, this is container 3 and try to append file host.ext for example, you'll get an error that this is read only system. But if I try to cat host.ext read the content, I can read the content. If I want to do the same for host2.ext, I should be able to do it as well. But if I try to create directory or create a file or change a file, I will not be able to. All right. So hopefully this explains exactly how this works. If I get here, I don't need container 2 anymore. So I'm going to exit. So I'm now back on the host. If I do docker inspect container 3, let's see how the the mount would look like. So here readrite is false. Whereas bind is the type and then the source and destination are clear. And if I look at the host config, I should also find some highlights about this here. Host config binds. And here's the bind. But it shows that it is read only. All right. So hopefully this is clear to you. All right, let's now go over what Docker Compose is and what we can use it for in order to deploy multiple container applications and we don't have to do it one by one. So we can define a script that is going to have the configuration for the desired containers for the end state that we would like to have and then docker compose will execute that file and deploy what we need to do. So docker compose can help us to simultaneously create start stop or delete multiple containers on the same docker host. So we are still focusing on a single Docker host and that's what we are working with. So if I have an container that is supposed to run a NodeJS application and maybe I need a database also for this application then I can use docker compose in order to create the many containers that I need for this application. So what is docker compose? It's nothing but a tool software tool under docker that we can use it to define and manage multicontainer docker applications. So where do we define it the multicontainer application we create a file by default or the default name for that yl file is docker composyiml or yl. So you can define all your environment including services, networking, volumes, containers, dependencies, all of that could be defined in a YML file and then you can execute the AML file using docker compose using a single command and this will deploy whatever you have specified inside the file. And if some of these containers you have docker files for defining how the images for these containers should be then you can also use docker compose to build the images or to build the images and then create the container. So these both are possible and you can define or specify where to locate these docker files and docker compose is going to take care of the rest. So let's look at how the workflow would be. So you need to define the YAML file which is by default the dockery compos. That's the default name but you can use alternate names if you would like. This YAML file will reference docker files. If you have docker files that need to be used to create images for one or more containers that are defined in the aml file. So when we have that then docker compose when you execute the ML file is going to grab the docker files and then build the required images but it can also pull readymade images from your local host or maybe from docker hub and then it's going to create the containers that you need and as we build it with a single command we can also tear it down with a single command we can stop it we can restart it and we can delete it completely. Let's now look at the docker compose file structure. How does it look like? What's the syntax? How do we define the containers? What are the names if any? What are the parameters we need to define? That's what we are going to look at right now. So the first thing we need to know about docker compose is the section called services. The services is written and these are the containers that you would like to create using this docker compose yl file and it is written lowerase services and then a column. So in this example we are going to create three services or at the end we're going to get three containers. One has the local name in the compos file database front end and then back end. So these are the three that we are going to create and please notice the indentation. So each one of them starts two spaces from the left and then you started and these are all indented. So they are all at the same space or same distance from the left hand side. So I have database column, front end column, back end column. These names are locally significant only in the docker compose file. So these are not going to affect anything else. You can name it John Smith and Sarah if you would like to. That's up to you. The second thing we need to look at is the service image or the image. So if you have any of your containers is going to be created from a readym made image with whether it is on your local host or on docker hub. Then you can use the part image and again notice the indentation from here to here. So you have to move couple of spaces in because this is an item or a parameter that is under this service and the service name is database. So image lower case colon and then the name of the image or you can have the version if you'd like to the tag as we call it. Then if you would like for one of the services that docker compose is going to build the image for that specific service then we need to add the build statement in the docker compose file. Assuming that in this case we have a docker file in the same directory as the docker compos yl file then all what we need to do is to add a build statement. So in this case I'm assuming that front end needs an image created from a docker file and the docker file exists on the same directory in the same directory where the docker compos file is. That's why we type build lowerase colon and then dot means the current directory. What if I have the docker file in a different directory? It's not in the same directory as the file. How can I specify the path to that file? And if it is not named docker file, it has an alternate name. What do I do? How do I specify the path? And how do I specify the alternate name for the docker file? And where do I define that specifically? So if we assume that the back end has a docker file with a different name in a different directory, we need to define that here. So again it is going to be a build section. Again the indentation to the right build column and then we are not going to write anything here. We'll leave this this one blank and underneath again indentation two spaces to the right we write context and colon and then the full path to where the alternate docker file exists. So this in this case user project app. This is what we are assuming where the docker file exists and the name of the docker file can be specified using docker file colon and then the file name. Here the assumption is the alternate docker file name is file config. And please note that these two are on the same indentation from build. So this one and this one both are under the same build section. So that means these are parameters for the build. Next, what if I need to define a container name. So in this case under the service and aligned or equal indentation from the left hand side, right container name and colon everything lower case and then the name you desire to have for the container. I can have this under each container if I want to. Then what if you need to expose ports for a certain container? Then again under the parameters image container ports or build ports you can define ports colon and then enter indent two spaces and then hyphen comma host port colon container port and then close the quote. In some formats you can do it without the the quotes but it's better to follow one way that works for you and then you continue doing it. So this is how we expose ports. This is equivalent to when we do the hyphen p lowerase or the hyphen publish in order to expose the port with docker run. Then what if we need to add a bind mount to one of the services or to multiple services? What do we do? So again on the same indentation, same line, we write volumes and then colon and then we hit enter and two spaces to the right hyphen and then put the directory or the host path the folder the full path for the folder on the docker host colon where it's going to map inside the container. So the container path and the host path and that's it. That's all what you need to do for the bind mount. What if it is a normal volume, a named volume, what do we need to do? So in this case, you need to do two different things under the corresponding service. Let's say I want to do it under database. So what you need to do here is you will define the volumes again. In this case, you need to also indent. So this will be indented underneath and then the volume name colon container path. So this is an a named volume that you have to create beforehand but we haven't done it anywhere else and that's why we have to create that in a volume section. So we have the services section and at the same indentation we have volumes. So services is containers volumes is named volumes and then you can write the volume name. So as you can see here the same name is used here. Then what if I need to create a volume but it's not going to be named an anonymous volume. I don't want to create the container beforehand as we did in the previous slide. So what do I do in that case? You do the volumes, you do the indentation and you don't put the volume name. You just leave it blank and then do colon container path. So this is going to create a a volume anonymous volume or a volume with an anonymous name and it's going to be mapped to the container path inside the container. All right. So these are the critical ones that we need to create if we need to deal with Docker compos file. So now we learned how to do containers or services and how we define the container name, how you define the image if it is ready on the host or from docker hub. how to do the build if you have a docker file in the same directory as the docker compose file or if it is in a different directory and if it has a different and if it has a different name and we do that under the build. We learned also how we can expose ports and we learned how we can create volumes whether they are bind mounts or named volumes or they are anonymous volumes. So that's enough for us to practice a little bit and play with it in the lab. I'll see you in the next video. Let's now look at the docker compose command. So we have built the YAML file for docker compose and now we need to start creating stopping restarting the environment. What do we do? So there are multiple commands and they are all start with docker space compose. It used to be in the older version docker compose but this is the case right now. Docker compose build. If I have created the docker compos file and it has build sections under the services. So images needs to be built. Then in this case I can do docker compose build and it's going to build the images that are in the docker compose yl file that exists in the directory where you are running this command. If I have multiple services but I need to run one of them. So for example in the uh previous file we looked at database front end back end let's say I only need to start front end for some reason for some testing what do I do you can do docker compose run and service name which one database front end back end notice in these two commands I did not specify anything about the name of the docker compose file so this assumes that it is on the same directory where you are applying these commands you have the docker compos yl file in the same directory. Then if I want to run the entire service or environment that is defined in the docker compos yl file I do docker compose up. So this will build the images if they are not located locally and starts the container. So even if you haven't done the docker compose build this is going to do the build and run as well for all the services. So this command is for a specific service. This is for all the services. What if I need to run it in detached mode? I can run also up with hyphen d which means start the containers in detached mode. What if the file name is different? Then I can do docker compose hyphen f and then I can specify the file name and up. And of course you can specify the path for the file name and up. And that means a different docker compose file builds the images and starts the containers. And this is the minusd that I told you about. And then we have few other commands. Docker compose down. So it was up. Now I would like to stop the containers and delete all the containers created by docker compose up. And of course you can do down docker compos down hyphen volumes which means delete and remove the containers but also delete the volumes that they have been created. And in this case we are talking about the named volumes and the anonymous volumes that were created by docker compose docker compose down with hyphen remove orphans. Let's say that this docker compos file created containers but then you changed the file and some of the containers were removed but they are still on the system. They are exited or stopped on the system and I would like to remove the current ones and also the ones that have been before used and created they are now stopped and I'm not using them. So you can do hyphen hyphen remove orphans and of course you can combine volumes hyphen hyphen volume space hyphen hyphen remove orphans as well and you can do docker compose volumes and remove or orphans which is the combination of the previous two and also we can do docker compose stop which will stop the environment stop the containers and docker compose start which will restart the containers again. When you use docker compose to build an environment, docker compose will voluntarily is going to create a bridge network and all the containers in that environment that are created by docker compose are going to attach or are going to connect on that bridge network. So when you do this up minus D then and you do my docker network list you will find that there is one called Ubuntu default and it's of type bridge. Enough for the theory and commands and let's go ahead and start playing with docker compose. I'll see you in the next video. First docker compose files and see how they work. So let's go ahead and create our first docker compose file. I can do it in the nano editor in the docker host but VS code as an IDE will give you better support as you build because you have the Docker plug-in in VS code. So what do we need to do? I'm going to create first thing services and then I'm going to hit enter and then space space for indentation and I'm going to call the first service web also enter space two spaces and then here I'm going to write container name I want to create a container with the name dolphin at after the column we leave space and then I want to expose ports space space then I'm going to expose port 8080 on the host to port 80 on the container or the service. Then I need to define that the image is going to be engine X. So that's it for the first configuration file. I'm going to take this copy. I'm going to nano. The file name will be dockery- compose. That's the default name. Yiml yaml. I'm going to paste what we have typed. And then I'm going to do Ctrl X. Yes. And enter. Now if I cut that file, you'll find this is what we wanted. We need services. It's called web container name dolphin ad ports and image. Of course, you you may want to put the image on top, the container name at the end, but this is how it is. Now, before we do anything, let's see what networks we have on the host. And you'll find that we have the three default ones. We don't have any other networks at the moment. All right. So, let's bring docker compose up. So, we do docker compose. Note that in the file name there's a hyphen. Here there is no hyphen. And I'm going to write up and minus D in detached mode. So what's happening now? Running one of two creating network Ubuntu default then network Ubuntu default and then running two of two where container dolphin ad has been created and now is started. So let's do docker ps. As you can see we have a container up. The name is dolphin eb. The mapping is done port 8080 to port 80 on the container. So this is on the host side. This is on the container side. Has been up for 20 seconds and it is an engine x image and it's running in detached mode because we instructed that. Now let's clear let's do docker network ls. Find out if we have any networks any new networks. And if you look at the last one, you have Ubuntu_Default bridge. It didn't exist before we used docker compose which means that this was done by docker compos and also we have seen it when it was running when we did the docker compose up. All right. What if I inspect the networking in dolphin at the container. So let's look at what we have here. So first thing it has been on a custom network a custom bridge as you can see the IP address is 17218 the default bridge is 1727 and for the network binding for the container it is on Ubuntu default as you can see and you have an alias of web for the service and dolphin ed for the container. And here we have the ports ATTCP on the container to the host IP whatever that is and then port 8080 on the host. So everything we have created is available in the settings that went into the container and the docker compos version. And who is the maintainer of the image? The rest is not networking. The the rest is just the normal stuff we have seen before. Now let's see if I can get to the container from the outside because we have seen the mapping of the port. Let's find out if we can do it. So I'm going to take the public IPv4 address of the docker host and I'm going to go out and I'm going to open a browser to port 8080 as we have typed it. And as you can see, engine X. So container is created, publishing port is done, everything is done. And now I can get to the default page of the container. So that's the simplest form creating one container using docker compose. But that's not the strength of docker compose. What if we do docker compose stop? Now it has stopped the container as you can see. And if I do docker ps I don't have any running containers. If I do docker ps minus a then I can see that there is one container that was stopped. And I can also, by the way, do docker compose psfs because if I have containers created without docker compose and others with docker compose, this is going to tell me if I have any created and running using docker compose. And if I do this minus a, it will tell me the ones created by docker compose and are in a stopped state. All right, let's say I want to start it again. So I'm going to do docker compose start. And as you can see it is starting. And if I repeat the command, you'll see that there is one that is up and the service is web and the name is dolphin add here. And this is the command, the entry point uh command that was done and the port mapping that we have instructed as well. And it shows you here the time it has taken to bring this up. Now let's say I'm done. I don't need it anymore. So what do I do? You can do docker compose. So we do stop start and now if you do down then it is removing the container and removing the network as well. So if you do docker network ls again you'll find that we don't have the Ubuntu default anymore. And if I do docker compose ps minus a minus a. And you see that we don't have containers exited or up and running as well. So let's now do this docker project. And what we are going to do, we're going to assume that you are now an infrastructure and someone who is an expert in Docker and someone hired you because they need to establish a website using Docker on AWS and they have specified the specific template they would like to use and they are going to provide you that template or maybe you are on the template website and you can buy it for them and you just bundle that in your cost. So they like the template and now you are going to do the project end to end. You are going to build for them the front end which is the website. So we are not going to touch on the database in this project but you are going to build them the website using the template using docker and you are going to build it from the docker file to the image to establishing that website and making sure that it is live online. So let's find out what we are going to do. So let's assume that they have been shopping around and they liked on Invato Elements. They liked this template and they would like to use this as their website. So this is what you are going to build for them. Database is going to come next but for now they want to see that this website is live and how it would look like and that it can be done with containers on AWS. So they like that and they provided you a link where the school website or the template is on GitHub or maybe you bought the template and you uploaded everything on GitHub. This is out of scope for now uploading the templates and buying the templates and all that but the templates is available right now and it is on GitHub and you have the link to clone it and now it's time to start working. So we start from GitHub. We're going to clone that. We're going to copy that, download it into the Docker host. And then from the Docker host, we are going to build the Docker file that will use the code that you have downloaded and build the image. And once we have built the image, everything else, if you have done it right, everything else becomes easy. We can use that to run with Docker run and build the container and then test access to the container from your laptop or their laptop. just to see how it looks and then we can think about the next phases and then we are going to push this new image that we have used when we put all the code inside the image we're going to push it to docker hub so it can be reusable or we can edit some stuff and then do version two version three version four and so on so it is now available for collaboration available if you are the consultant and you are going to get your pay after you finish and then you will leave it so now at least you have already uploaded it to them and now they can hire you whenever they need to make changes or maybe their developers can take it from that point onwards. Either way, this is what we are trying to do now and we are going to build a website that will look like that what the template shows on the Invato elements website. So this is how it will look like on the docker host and on the container. So this is how we need to build it. So on the docker host when we clone it on the Ubuntu machine on the docker host we are going to have a folder once we clone or download what's on GitHub it's called docker capstone project one and if we list the content of this directory we're going to find school website and if we ls the contents of school website we'll find index and error and about there's a lot of things and then we're going to also find directories called assets documentation source and so on. So this is how it looks like on GitHub and on your laptop when you download it. And we're going to verify this. The way we want this to be is since this is the content and the index html file and so on, the index html file in engineext the default one is under user share engine xhtml. So what we need to do is we need to get this content with these directories and we need to get it copied under this folder. So there will be a copy here and that's how when we browse to the container the website is going to be launched or it will appear as per the template. So this is exactly what we need to do. Of course the key docker skills that we are going to demonstrate doing this project is how you can write and build docker file for a static website server or the front end which is the template we talked about. Understanding the container life cycle from build, running to stopping and removing. Managing ports and volumes and static content in containers and basic use of docker compos for service orchestration and of course containerizing a code that you have been given for an application or a website into a container using docker files and then creating docker images. So let's go ahead to the console and start working on this. All right. So here I am in the console right now. What we need to do is we need from GitHub where the project is either if it is your account you can go ahead and copy the code or the access how to get to it and it's a public repo so you can get the files without any SSH or anything and it all depends on how you would like to get it. In my case, I'm going to download it to my Docker host using the command get clone and then the URL I just copied. And now this is going to be under my Docker host. So, as you can see, it has created a Docker Capstone project one. And if you'd like to see what is in there, I do ls. Okay. And then we have the readme file and the school website. And if we check here, it's the readme file and the school website. If I go into the school website directory. Okay. So I have to go back into here. And if I want to go now into the school website directory and we do ls, you'll find that there is so many files including index html. So this is the main page that we have seen in the template. So this is what we should see and this is what the index html is going to display. But then it's going to show all the menus and so on. So I need to make sure that at the end we're going to end up with something like this that has these pages included. All right, that's that's cool. So we have all these files here right now. What do you want to do? So I'm going to do one step back into the project directory. And now it's time to create the Docker file. So let's do a nano docker file. And I'm going to have this created from engine X. It's up to you to choose the version. For me it's latest. I can add column latest or just leave it blank. Then we need to copy the code of the application of the website of the front end into the right directory into engine X. What is the right directory into engine X? We know as a destination it's going to be / user/share slash engineext/html. But what is the source? The copy is keen on the relative path from the directory that is considered the build context. What is the directory that is considered the build do context is the directory where I created the docker file and that is the docker capstone project one. So from there you need to point to where the content is. Let me just open this so I make it easier for you. Let's open a new terminal. So it will be easier to understand what I'm talking about. Stud. And now if you do ls this is where the docker capstone project and this is where I am creating the docker file. So that's why I'm going to move inside it. If I do ls now we have the school website is where all the content is. So I need to tell copy relative because I'm going to create the docker file right here inside this directory. So relative to where you are where the docker file is and where the build context is. Go into the directory called school website and copy all its content from where you are from where the docker file is. Please copy the school website. See, I just made a mistake. It has to be exactly the same. And of course, I could have came here and just copied this to make sure that we don't do mistakes, especially if the names are long. Can just go here. Delete all of this and paste it just to make sure we're not doing doing any mistakes. Now, this is the source. What's the destination? As we mentioned, user share engine X and HTML. What if you working with Apache? Then you need to find out the root document of the Apache. What if you were working with any other tool or any other server? Then you need to find out where should the main or the root document of that server be. And this is where you want to copy the files. And then we need to expose port 80. That's all what we need to do. So Ctrl X, yes, and enter. Now we have the Docker file. Let's cut to make sure that we have it right and we didn't do any mistakes. Now when you Oh, see docker file. So now from engine X latest and we are now as you can see we are at the capstone project and this is where when we did ls capstone project and then we have one folder or one directory or subd directory and that is the school website and this is where all the content is when we did ls here everything was inside it. All right so it looks okay to me. Let's do a docker build minus t. I'm going to call it web school and the build context is the current directory. Hit enter and it looks like it has created the image without errors. Now let's do docker images. And we have a web school image right here. And now it's time to do a docker run and test that to see if it works or not. So I'm going to do it detached. And then I'm going to do minus P. Let's bind the host port 80 to the container port 80. I can do a different number if I want. I can do host port 3,000, 4,000, 5,000, up to me. But since I know that this is not used right now, I can use 80. Nothing stops me from that. What else do you need? I'm going to provide it a name. I will call it web school. What is the image? And the image is going to be web school. And if this is only for testing, what you can do is you can also add the option rm. So when you are exited, the container is going to be deleted. And let's hit enter and see what's going on. So now I should have a container that would look like the template available through port 80 on this public IP address. So I'm going to copy it. If you don't have this or if you close this at the beginning to have more space to work, you can come here and you can copy it from here as well. So now let me open a browser to port 80. For port 80 you don't have to type it but it's up to you. And as you can see now we are from port 80 we are having something similar to what we have seen here. Right? So this is how it looks like shell in the background as a watermark and then home about classes and so on. And in the container we are having the same and it looks like the same. Yeah some images are missing because they need to be added. We don't have these images but otherwise the templates and the details they look like they are available here now. All right. So we have built that from the template. We have containerized the template and now it's running inside inside a docker container. So it looks like we have been successful so far. Okay. So what what else do we need to do now? Since I know that this one is working, leave it working for now. What we'll do is I need to push it to docker hub and I am logged in into my docker hub and if I go in this is my account and if I look at repos I have no repos available and I can create one and let me try and call it school website version one or I can push the tag as version one if I want. So I can just call it school website because you're going to have multiple versions. This is the template for the school website front end create it. Okay. So it's empty right now but I can take this command here as you can see and I can use it in order to tag and then push. So I can do from here docker tag and then the image name. Of course I could have done it just paste this command and instead of push I will do tag now and then I will delete these two and then I I need to decide on what is the tag that I'm going to use. Is it going to be latest or because this is the first one I'm going to call it version one. Okay. So now I'm tagging that um sorry. Okay. So I need to put the original name first which was in the docker run. So let's put the name of the image web school and I'm going to get here. So this is the original image and this is where I want it to be tagged as. Hit enter. Now if I do docker images, we'll find that one here that is ready to be pushed and it's version one. So next step is I I will docker login if you are not logged in but I am logged in. Then I'm going to do docker push the name from here and it is version one. So it's exactly this one and version one. Let's push and see what happens now. So it's pushing the image. If it finishes properly, then we are done with this hands-on lab. So, it looks like it did it. And if I go to Docker home again, Docker Hub, and refresh this page, you'll find that we have version one. Click on see all. Then this is the image that you can pull and use it. So, let's do one thing. And this is optional. It's up to you if you would like to do it. What I will do now is I'm going to do cd and I'm going to delete the files from here completely and I'm going to stop the container as well. So docker ps minus a. I'm going to do docker rm minus f and then I'm going to stop this container which is running the website right now. So if I go here and I reload, I shouldn't get it. Yeah, because I stopped it. Okay, so that's a good step. If I do docker images, I'm going to find the web school image here. So I want to delete it as well. So I'm going to do docker rmi. And if I do docker images again, I don't have it. And also I'm going to docker rmi the one that we pushed the tagged or the alias. So version one. And if we do docker images one more time, we don't have it at all. So I don't have the image web school. I don't have also the one I pushed to docker hub. So what do we have? What's what do we still have? LS we have the docker capstone project. Let me also remove that one. I'm going to do rmrf. So remove it even if it's non empty. And I'm going to paste that. Now let's see ls. I don't have anything. So what I will do now is I'm going to use the docker pull that we have seen to test that the image that we have uploaded is working. I'm going to go back and I'm going to do a docker pull already exists because there are layers cached. That's fine. Docker images. I should find version one available again. And if I do docker run minusd from this image v1 and expose port 8080 because I'm not using this container is running and if we try the same IP again I should be able to see it again. All right. So what we have done quickly we have built the docker file after we downloaded the content from GitHub in the docker file we have copied the content of the project the code of the project the code of the application the code of the front end it's exactly the same process no matter what you are trying to run in the container and then we put that into the right folder under engine x which is the user share engine x html why that folder because this is what engine x browses or displays when someone goes HTTP into the EngineX server. From there, we were okay to build the Docker image from the Docker file. And then we built a container from the Docker image and we exposed port 80 on another port on the host. 80 on the container mapped statically to a port on the host. We browsed to it. Everything worked fine. So we went back and then we tagged the image with the Docker repository path, the account name and the repository on Docker Hub and we tagged it as version one because this is the first one. Maybe we'll do modifications and then we pushed it into Docker Hub and then we pulled it again and we used it and it was working fine. So project is 100% success. It shows you the life cycle of an application from the code into a docker file and how it gets put the right way into the server that you are using and then it was available for access. So what is missing now the back end and the database to provide all the images and course details and everything that we need. Congratulations on finishing up the course. If you would like to learn more about Docker and at the same time support us develop more free and quality content like this, consider buying the VIP package that includes a lot of things. So by doing that, you are going to have lifetime access to the course and any updates that happen to this course. You are going also to have access to another 8 hours of video content that will have more hands-on labs, more topics covered at a deeper level. And you will have a second realworld project that will help you sharpen and harness your real world experience and your portfolio as well. You will have an access to a community for faster Q&A support throughout the learning. And you will have of course quizzes and assignments in each one of the modules. And most importantly, you will have access to the 330 PDF guide and all the hands-on lab scripts that we have used in the course. So if you are willing to support us and also have a great return on investment through further free content video that we are going to generate this is going to be the link www.dolphinaded.com/courses/doccker. I hope that you are enjoying or have enjoyed the course and looking forward to see you in further

Generated algorithmically for Search Engine Indexing.

Summarize Another Video