and here we go, we started recording. In that last exercise, what we did was that we had used Docker Compose, the different way of using Docker, like instead of running it directly on the command line, we have a different approach to running Docker. That approach is what I used in the last exercise. That exercise has been documented now. I have written it down here and I will identify what location is that. You can also get to that same location where I am going right now. That location happens to be, I think it is Docker usage or something like that. Let's get to that point quickly. I think it is this one, 33, that item here, that's where it begins. The entire Docker exercises that I have been doing, I have made sure that I have written down here now. You can begin from this point, start through, read up a lot. This is the description part of it. Then comes exercises. There are a few of them that we have done already. This one is an exercise that requires a lot of horsepower. If you have it, go and run it. Otherwise, don't bother. I'll just give you a caution already in that. In that this machine, I have in the machine here, the VM, I have given this machine 26.3 gigabytes of memory and a bunch of, I think, three or four cores. That VM is a large VM. That's the reason why it succeeds doing this exercise. That's a caution. If you have a big machine, go ahead, play with it. If you don't have it, don't bother. Just skip this exercise. You just watch the video of what I did. That will give you a perspective. I'm trying to see if I can further reduce the time it takes for the exercise to a little bit less because this is more of a demonstration of the capabilities of what you can do. This is just a weird example, which is not standard. Not many people use it this way. The point here is you can do whatever you want. It's basically any application you want to run, you can run. In fact, just to supplement this idea, which is I'm creating a GIF animation file using a video file and doing that in Docker. That is just one of the ideas. What you will be surprised to notice is I watch television using Docker. I'm not joking. I'll give you a live demo for a few minutes just to give you a perspective on what you can do with Docker. This is me in my home watching live television. I'll go to live TV and go to King5, for example, and just play the television. This is actually running on the back end in a Docker container. This is your television. I don't need to play the video, but I'm just showing you that that video is coming straight from a Plex player running in a Docker container. I'll show you where it is right now. Here is an example of what you can do. You can basically do anything that runs in a computer. You can make it run in a container, pretty much everything, except there are a couple of cases that you have to have a direct access to a full-blown hardware machine. That's a different, very corner case scenario, but most of the applications that you will see, you will be able to run just fine. That video that I mentioned, my television, live television that works, I'll go in a Docker container in my home in a different computer, so I'll go to that machine. There you will see that there is a process running, and it is running this container ID, and it is running the software, this image, and it has been up and running for the last eight hours. Here you can also check the Docker logs. Here are the logs for the container that is running, and I can see that it has recorded my television show and also edited out the commercial skipper. The commercials that most people see when they watch television, a TV show goes like this, and then at some point, you will have an advertisement, a commercial pop-in. If you happen to record that show, what this thing does in the Docker container is it will cut the commercials out. That's this segment reference, this log entry, showing you that commercial has been trimmed out. That is one of the reasons why I have not seen commercials for quite some time, unless this process fails for some reason. If this thing fails, commercial skipper, in that case, then I will have to see the ad, because what I do is actually never watch live TV like most people do, I watch it recorded, so it's a recorded show that gets reviewed whenever it becomes available, for example. You can see that there are recordings available for Saturday Night Live and for late night and like that. Whatever TV shows pop up, I tend to record them and I watch them. Currently, something is recording right now. My wife is probably watching this L.N. DeGeneres show, so it is getting recorded or something like that. Some activity is happening. You can see that here. All these things are all running inside this Docker container in a Macintosh Mini. There is a Mac Mini, which is running Linux, by the way. That Mac Mini machine that you have here is running this Linux kernel. What is the advantage to running this through Docker? In other words, you have a unique virtual environment in which to run it so it can't be corrupted by other stuff or what? It's easy for me to manage it, update it, restart it, fix bugs. Yes, this is an open source project, so I also make edits to it. The advantages primarily are that, by the way, you don't have to run it like this. The point here is that you can and that's the whole idea behind using open source is that nobody actually prevents you or forces you one direction versus the other, but there are certain benefits of doing things in Docker container that I can get multiple things running in the same physical machine. Here, this Fedora workstation that I have running is actually a Macintosh Mini, and that Mac Mini is running Docker. In that, I currently have only one container active, but in the same box, I can put 10 other containers and get other things also done on the same equipment. This is conceptually similar to running multiple applications on the same Mac Mini or same machine. But then, keeping it isolated from one another, I can basically individually manage and take my container, run here, run it another place, run it outside in the cloud, whatever I want, I get that flexibility. That is what I really, really love, and that is what you will see in more upcoming exercises is the ability that it gives us to basically contain limit, put that in a box, and then take it anywhere you want and run it there, irrespective of the machine under the hood. It has to have some Linux at the foundation, and then it will run. It will just run without complaining about, hey, I don't have this dependency or I don't have that thing because I'm basically aggregating all things I need in a Docker file. That Docker file is built using the syntax that we have seen before, and I'll show you more, and we have more Docker files coming up in an exercise which is in about 10 minutes from now. This Docker that you see here, which is running the TV, this television that you saw, this Docker container actually started because of a Docker compose file. You can see the Docker compose file also, and that compose.yml will show you exactly how I am mapping that configuration inside my home. The Docker compose file begins at that line here. Let's review that quickly, and I'll quickly just go through this and move forward. Not spending too much time on television watching, but the point is here is the version. I think that is not very legible. Let me adjust that. Now, this should be a little bit better to read. The version of Docker compose, I think the ink should change. Docker compose version, and then here are the services running. What are the services? None. Any other service here in the same line here? Nothing. Only one service. Now, I have some volumes defined, and then volumes are actually not on the local machine. They're not local. They are externally mounted at this address on an NFS mount. It is actually a different machine that runs my storage. That storage is called free NAS. That's where I am not storing it on this machine, this Mac mini, but storing it externally in a different box, which is like my, I think it is about eight terabytes of protected storage that I described a little bit before. I'll show you that also at some point, but that's where the storage is. This is where the recorded TV and other videos and pictures, and I have about 63, I don't know how many, some exorbitant 63,000 pictures ever collected. I just stored everything in that location. This is backed up on Google Drive. G Drive that you have, I think that you know. You also have access to it, by the way, if you wanted. I can give it to you. Unlimited, infinite free storage that you can use to backup. I have backed up this eight terabytes onto the Google Drive, and this is where my actual storage is. This is the volume I'm mounting, and that was just the volume portion discussion. Let's also inspect apart from this volume mount. Let's see what that service is doing. The service is called Plex. It is running a container, and it has a host name called mini. It will restart if it is stopped, and it is using this image, that image is created with a Docker file. It has a network mode host, so it basically appears as if it is running directly on the host machine with the same IP address. It has a volume mapping. These volume mappings have one, two, three, four, five, five different volumes, and then there is an NFS mount here, and this NFS mount coming straight from this storage, external storage location. There are some local mounts also for configuration, for transcoding, and for data storage, and some pictures, and a time zone location setting also for the American Los Angeles time zone. There are some port mappings. These ports are necessary for that particular software, which is Plex, to run correctly, and that's what we are doing is opening up these ports, mapping them from a host machine to the container like that. Just like we do 80-80 mapping, same idea here. This is 1900 to 1900 mapping. This is this number, that number mapping, and that is the port setting mapping. We have an environment ID, and that environment ID basically gives you the ability to change the user that you want to run as. This username is different from the root user. This is the currently logged in user. I'm currently logged in. The user happens to be this UID and this GID, and that is one of the reasons why you saw that the last time I was going to run WordPress and I was running into access permissions is because we were using a generic image provided to us by WordPress, and we did not have this environment definition defined to run the Docker container for WordPress with a user which is not root. We were expecting a permission structure from this user, wwwdata user, which runs the WordPress application, and the actual file system was owned by root. It was preventing write access, so no write access error. That was the error that you saw the last few minutes of the last session. That was the root cause of the error because the ownership of that file system was not in the control of the process that was writing it to. It was failing to save any data. Upload a picture, it would not save. That was the root cause because we had not set these parameters correctly for ownership. We also have some other things. There is a cloud service here included, so I need to connect this particular flex container with a cloud service, and that connection happens through this claim. There's a claim token that you can see that, by the way, this token is probably private. Yeah, it is definitely private, so I shouldn't have shared it with you, but yeah, I'll reset it later on, so it's no big deal. That's a secret information that I should not have exposed, but I have. All you can do is steal my TV recordings. I don't think you will do anything like that, and the exposure, risk exposure is very miniscule. All you can do is basically look at my TV shows. Yeah, it's not that risky. There's a loud network, meaning this is the home cider block I have. Inside my home, I have that cider, which I have allocated, and so that's where it will play this TV show. I have also further configured it to make this TV showing business watchable from anywhere on the internet. I have another mapping that allows me to do a port mapping like this, which allows me to watch my television show from anywhere I feel like, literally, and that requires another service that I have created. I think it is probably somewhere here. I can just point it out to you also. You can go app.plex.tv, and that's where it exposes a port, and I can continue with email and login, and there you can probably see my settings, which I will now show you. It is going to show the settings, which shows that I am currently authorized to remote access. It is fully accessible outside my home network, and this lets me access my television shows that I record from my antenna. There is an antenna in my home. That antenna has a tuner that tunes, and then this Plex thing will record and cut out all the commercials and save it for me when I want to watch. By the way, I never watch television. Maybe once for 10 minutes while I'm eating something, but that's it. This setup is primarily for my wife, so that she can watch whatever she wants, whenever she wants, whichever location she wants it at. That's the idea behind this whole setup, and it is running in Docker because why not? That's the real answer, because why not? It also gives me a ton of flexibility to package it up and run it the way I want, manage it the way I want. That's the primary reason. Yes, it is nerding out. But that's what I do. That was a quick demo. Now, having said that, in practice, yes, you can do it this way. This is the officially supported method also. By the way, Docker is a full-fledged supported method. Having said that, I'm going to quit from there. I wanted to point out that this is a long exercise, this one you're looking at, so don't bother doing it unless you have a big machine, in which case, yeah, go do it. I will figure out a way to reduce this time it takes, and then at that time, I will remove the cautionary note. Until that time, it is there. Just read it and watch the video that I did. The last session, I think I did that. We also discussed a little bit of persisting container data. We also had a cheat sheet and then an actual exercise in Docker Compose. Here was the write-up. This write-up was not there the last time. Now we have a write-up. It actually uses this Docker file. We have Docker Compose YAML that we have here. We can open up in Atom. You can see it. It is the same file that we have here, which is this file, and that's what we were running the last time. It is 27 lines of code that completes our Chef exercise, practically speaking. If you look at currently running Docker containers, we have a bunch of them. Let's kill them and quickly bring the whole stack up. It is so easy and effortless is that once you have such a setup in your hand, it becomes effortless in creating something as quickly as kill every container that you have, like that. It's not killed because I did not type properly. Now it killed. Now we don't have any containers running. Now you want to get the whole stack up and running. All you do is Docker, Compose, up, and put this in the background in even mode so it goes away. You have the command line available to you. You can check the process is running. At this time, your WordPress setup is already up and running. You can just go there. You can see that you have WordPress in your local machine. There it is, your WordPress. Come on, show me. There it is. With the data protected, by the way. The data is protected. It's not happening because we haven't actually tweaked our user permissions. We'll do that at a subsequent time. We'll go into details about how do we configure large-scale storage systems using industry enterprise-grade storage solutions like NetApp and EMC and all that. This is just a quick and dirty way of understanding storage. We'll actually use, in a corporate environment, use enterprise storage like EMC or NetApp or something like that. In a cloud environment, we'll use the cloud-provided storage solutions. But in proxy, for right now, I will be using a different type of storage solution, basically the local file system. I created a setup that you can actually visualize what is happening in a practice that you can see when you take these things in the enterprise, how will you actually manage the protection of data. That is something I want you to pay attention to when we go into the next set of exercises, which is a buildup on what we just did here. We have a WordPress running. We have a Docker Compose file that looks like this. Now, we'll play with this Docker Compose, a lot of variations to the same idea, and that you will see in a different folder. That folder is called cd-docker-files, that folder. It is cloned from a remote location. The remote location is, go to the next page, and you will find it right there, this one. Let's see the other exercise also. There is another exercise here called more Docker files. Let us see what this thing is. I think this is a simpler exercise. I want to do this one first before the other one. I'll clone this and then bring it here. Go outside of the Docker file folder, go to the home location, and then git clone. I cloned that one, more Docker file first. Then I go to the more Docker file. This is just one more example of Docker file. Let's go see this in Atom first. It has some variations to the way we deal with Docker file. You will see and appreciate the differences or your customization that you can do with it. Here is the Docker file itself. Let's go see it. It is a pretty small and simple Docker file. All it has is the label from NGINX. That's the beginning point. The maintainer name is me. Then I'm copying one, two, and three files. Very, very simple. These are the index file, the reset, and the style sheet. These three files, I'm going to copy that over into user share NGINX HTML location. Simple concept again, but actually somewhat decently constructed index HTML as opposed to just a quick and dirty. This is a properly done HTML file. You can see now what we do with it. What I like to do is to build the image using this Docker file here. How do you build the image? You say that I want to Docker build dot. Docker build dot. Dot means this one. Build and this one, meaning this folder, this dot. Before you put a dot, give it a name. Tag it with some name like more Docker file. Just a name, made-up name, and then dot. It will build the image. If it doesn't have NGINX locally available, it will download it. Then it will copy the three files, one, two, and three, and it's done. It's called more Docker files or more Docker files. That image is now available four seconds ago. This is the image ID, and now we can use it. How do you use it? Just run, Docker run, and then more Docker file. Then it runs, and then you can see it in localhost. You will see that this time it is not WordPress, but it is something else. I have to refresh. Is that thing still running or what? I think I must have been running multiple things. Let's go check whether I deleted the older Docker also or not. Docker ps-a. WordPress is still running. That's why it's showing WordPress. Let me go to a cleanup. Docker kill everybody. Where is that? Everybody dies. That means this should disappear and unable to connect. Having done that, let's go run Docker file one more time. More Docker file one more time and see. See what we get. We don't get anything quite yet. We have to check logs. Maybe it's running on some other port. We'll say Docker run more Docker files and put it in daemon mode. Let it go. Something not found in path. What is not found in path? I see. The way you type is not dashd at the end, but dashd at the beginning. That's what was the problem. Let's see this thing. It runs in the background. Yes, it is running. It's running right now, is it? Up and running for three seconds. That's the one that we are looking at. The other two instances are the failed attempts. We'll kill them or maybe not, but we'll focus on this container ID and see what's going on inside that container. Is it actually showing us something or not? We'll go inside the container to diagnose. Here we go, Docker. I think it is silly for me to forget that I have to do a port mapping. I'm going to kill everything again, and I forgot the port mapping. That's why it's not showing you anything. Docker run with a dashd option, and you still have to do the port mapping. This is dashd and dashp for port mapping, machine port 80 to container port 80, and now please run. Now this should run and show you the result right there. Here it is. That's the result you see. What you are now looking at is the output coming from this Docker image, which is created using this Docker file. Another simpler example to understand and remember to not miss the port mapping idea. If you miss that idea, it will not actually show you anything because this container is not directly exposing anything outside. It only does when you ask it to map a port like this. I did not do the first time. I did not have this segment. That's why it is not showing anything. Now it is showing you at least something. With that understood, I will now clean up again. Here is the cleanup action. I'll go outside this folder, do the other exercise. This example is a very simple one. We'll skip and move forward with the other little bit of involved exercises, by the way these are. That is collected in a folder called Docker files, plural, and that is downloaded from this location. You can see that location is this one. You can also see the same link here in the website. In the web location, you will have this link, the second link after more Docker files. After this link, we just did this one. Now we're going to do this exercise. This exercise is a multi-part exercise. We'll do this in iteration. It has lots of things inside it. Let's go do that first of all by reading what we have. We have cloned it already. If you haven't cloned it, you can just clone it. I have it cloned already here. I can say git pull and you will see that it's already up to date. There's nothing to bring because it already is available locally. I can see that git status is already clean and matching what we have on GitHub. We basically don't have to clone again. Having said, you should clone because you will not have the folder. You can clone by going to this location. There you will find a clone link right here. That's the link you could take to clone HTTPS and clone the whole thing in your command line. That's when you will receive this folder called Docker files. Then you open it up in Atom. Atom folder opens up. You can see it here. Now we'll put this window on the left side. Oh, not this window. This window on the left side and the other window here on the right side. Maybe left and right are mixed up, but it doesn't matter. Side by side, two windows. This command line is open with Docker files folder. Let's go review what we have in that repository. In this repository, what do we have? In that folder, we have cloned. We have a git repository. We have a folder called app, which is where one Docker file sits. There is another folder called data. That's where another Docker file is sitting. There is a folder called etc. We store some custom configuration for database called MySQL. We'll talk about that later. That maps to MySQL, by the way, as you can see. Then we have a step-by-step folder. This has the step number one and corresponding one and another one. Step number two, another two, and then another two. We have a.gitignore. We can actually ignore that. It's not relevant. Then we have a bunch of files here, one, two, three, four, five. We'll see what these things mean as we go along. For right now, let's begin with step number one. That's the beginning step. I will now erase my ink and then read that step number one. This is a compose file, Docker compose YAML file, as you can see it already. The corresponding split down will show you the Docker run equivalent command. Now you can actually begin to understand how you write Docker compose when you have the actual Docker run action available in your mind. If you know what you want to do, like in this example, if you want to make the font a little bit bigger, please tell me. I will adjust the font, but I think this should be readable. If it is not readable, please tell me. This is the image I want to use. I'm doing a volume mapping. I'm doing a port mapping. I'm assigning it a name. This is the image I want to use. I'm running in a daemon mode, in the background mode. That's the command I would like to run. This is just one command. There are lots of things to remember. The first thing you have done is created this structure, which is the Docker compose equivalent of the same thing. You don't have to remember all these. You just write that detail up in that other file, which is a Docker compose YAML file. If you identify item by item, this item image matches this reference right there. If you see the port mapping, this matches this line number three. If you see the volume mapping, this matches this volume mapping here, line number four. That's this segment. This service that I have created in this segment is actually a representation of what you see here. What I am going to talk about next is that how do you take a command line and create a YAML file like that? That looks like this segment here. There is a different YAML segment here also, which is this one. We'll talk about that in just a minute. What you need to understand is that you can take any Docker command and rewrite that in a YAML file configuration so it's easier to remember. You don't have to actually remember. You just save it in a file and run the command Docker compose up. It brings up the stack. It brings up the stack containing all the services that you have. I shrink it for no reason. This is one service. This is another service. There are two services in here. You can bring both of them together in one shot just by saying Docker compose up. Having seen this idea, I would like to now talk briefly about what is a reverse proxy, which I think I mentioned briefly already before in the last session, at least some point in time before. A reverse proxy is something that is a thing of it as a unit where a visitor is asking for, hey, give me this or give me that. Whatever they ask for, this reverse proxy will know where the thing is, whether this thing is or where that thing is, and it will automatically route that traffic to that location and this traffic to this location automatically does that. It understands who is asking for what. Is it asking for this or that? Accordingly, it will automatically direct the traffic. The traffic redirection happens transparently to the user. The user has no idea. That's the underlying concept behind a reverse proxy. Having seen that idea, I will now show you with a live example of how do you actually make use of this idea. In this segment, we have a reverse proxy already. This person, Jason Wilder, he has created a proxy already for us. We are going to use that image. That's the image here being used. We are going to first of all create a proxy. This proxy gets created. It is also a container. Any visitor will hit the proxy directly and ask for that. That may be something here in a different container. This person will ask the proxy, can you please get me that? It will say, okay, here. Another person comes in and says, can you give me this? The proxy will say, yeah, I don't have this. I don't know what to do. It will say 502 error. Some error will produce. It will say error. First thing we'll see is the error. What I'll do is actually instantiate a proxy right here using this command. I will just simulate that error condition right now. You will see that. Currently, before we run anything, I want to check my Docker instances are all clean. I have nothing running. I will now create a reverse proxy. Here it goes. I'll say go. It goes and finds that this Docker image is not available locally. Nginx proxy image is not available locally. Cannot find this image. It will go and download it. By the way, this person, Jason Builder, is awesome. Jason Builder has created this guy. He has created this Nginx proxy and that is forked like 1,928 times and there are 69 contributors. It's a pretty good product. We used to use this product, by the way, until three years ago in my company. This was the primary front-end proxy point. We have switched over to Kubernetes. We'll soon be starting talking about Kubernetes also. You will see that this proxy is running. Also, notice that this proxy is mapping the port number 80 correctly. If you go and ask, hello, proxy. What do I have for localhost? It will say 503, service temporarily unavailable because it doesn't know what to do with you. There is no service on the backside. That's the point. Having seen this, let's also see that we can add another service in the back-end. The service that we want to add in the back-end is we have a reverse proxy here which is running. It doesn't know what to show. There is a user who is going to ask something like, go to foo.bar.com. I want to see that. Please, proxy, can you? That is what I want to actually run here, this foo service. I will have to create another container and run that container and then tell proxy, hey, I exist so that anybody, any visitor that says, hey, show me this. Then proxy will know that this exists. It will just direct the traffic to you, to foo.bar.com, and it will just show up. The results will show up to you. That's the scenario. We have a proxy running, but we don't have this one running yet. We will create one right now, something to show on that location in that domain name or that host name. We are not using DNS right now, but we can use DNS if you want. If you currently go to foo.bar.com, you will see that it goes to my Kubernetes setup. That's default back-end, nothing running there. That's why in my configuration, everything that is not available, it just goes to Kubernetes because that's where I run all my services. If there is no such site, it will just go to that location where it will try to find and there is no site running, so it gives you a 404. That's where it goes there. That's the reason why it goes there. In your case, you will not see this result. You will see unable to connect like we saw in another example of prior installation examples where we don't have anything running, it will say unable to connect. That's what you will likely see. That's the 404 default back-end because I have a Kubernetes back-end by deployment. That's what it's producing, this result. What I would like to do now is actually go to this same location like foo.bar.com, but with a different browser, the curl browser. I'll say I want to go to this host and I want to get foo.bar.com, but point at the local host location and that will fail. It will show you service unavailable, 503. Services are temporarily unavailable because there is no foo.bar.com running yet. Only the proxy is running on port number 80. What I want to do now is to run that foo.bar.com. Here is how you run it here, the who am I example. That's a service available from JSON Builder again. It's just a test container that runs who am I service. Basically, it just tells who it is. That's the service I want to start. This service, we should actually have these three things side by side. Let me just re-layout my editor so you will see the whole thing in one nice picture. Here is the compose file, here is the split down, and here is another split down. Now you see all three components. What I'm doing right now is identifying the composition of the Docker compose file. First thing you will see, as you probably already have seen, is that this segment maps to this segment. The nginx image, nginx image, port mapping, volume mapping, port mapping, volume mapping. The same idea here. Similarly, this segment matches this portion. Let's see what we are doing here. There's a Docker run. The dash D option meaning it's running in demon mode. The name is who am I. It will tell you its name. Then we have an image called who am I, which is basically a piece of software that says my name is and the container ID. The container ID will pop out as a result. Here is a unique thing. This thing is an environment variable, dash E, environment variable. What it does is it defines this environment called virtual host. That's a signal to the proxy that I am who.bar.com. If somebody asks for who.bar.com, please send them to me. That's the request because I am this. That's the signal line number three is sending to the proxy. That's how proxy will know that, oh, you are who.bar.com. I see, I see. I know now. I now know that you are the one that needs to receive traffic because the environment variable describes that you are who.bar.com. That's what I will do now. Anytime anybody asks me, as in proxy, asks the proxy for who.bar.com, here somebody seems to be asking for who.bar.com on the local host, which is this machine. I don't know what to do with it, so I'll say temporarily unavailable. Next time, once you have this service running, which is this portion running here, you can actually ask this question and you will actually get an answer, a real answer which is not this error message. That's what you will now see once we run through this. I will now clear my ink and run the second container, this container, which will instantiate a new service called whoami. There is my second Docker container coming up. It starts. It's unable to find the image, so it downloads it and runs it. There are two containers running. One of them is running at port number 80. Let me just show this again to you here. You can see that one container, which is the proxy server, is mapping port number 80 on the machine to port number 80 on the container. This is the machine port and the container port. That mapping is clear. The new whoami container is exposing port number 8000 and it has called itself as the environment variable, who.bar.com. That proxy knows that who.bar.com is that port on that container. It knows that way because of this flag. You can see the same flag here in the environment. Same flag. That flag is what I'm talking about here. That's how proxy will know that you are this. Now that we have those two containers running, we will go and check. How do we check? We just type corl, like this, specifically like that. We get the answer. It says I am and the container ID for that container. The container ID is this ID, which is the whoami image container. That's the response you get. Now that you have this container running, this one, this one, it responds that I am that ID. Now you know that the traffic is flowing correctly. Now if you ask for something like just local host without giving the header host request and just say local host, you will still get the error. This error 503 is coming from the local host proxy because it doesn't know what to do with it. You did not tell what you're looking for. In here, you did. In here, you did not. It doesn't know what to give you, so it shows 503 error. 503 error, unavailable. Whereas in here, if you ask for show me foo.bar.com, please, on this machine, and so it gives you the correct answer expected, which is that ID, I am that ID. That's the idea under the hood. If you want to see this in a browser, you have to do some changes to the machine. First of all, use a proper DNS. We don't have a DNS set up yet, so I'll now set up and show you the same idea in a browser window. Right now, there is no way for me to send traffic to foo.bar.com and make it go to this machine. There is no current way. If I go to local host, well, I can go to local host, and I can see that it is 503, not available. What I really want is anytime if somebody types foo.bar.com, then the request should actually go to this machine. It doesn't. Currently, it goes to Kubernetes in Google Cloud, at least in my setup. In your setup, it will be lost. It doesn't know where to go, so it will be stuck. If you ping foo.bar.com, you will see that it goes to Google Cloud. That's pinging right there. I'll break it, and I will need to change it. I need to change this to go to this machine, please, so this machine, which is what I want to do. What I'll do is I'll go sudo vi hc host and type the password and go modify the host file. What I'm doing right now is a temporary override on the DNS system by editing the host configuration. It's an override. Now, only on this machine, you will see this succeeding and what I'll do is put in the IP address localhost 127.0.0.1 as the place where foo.bar.com runs, and then I exit. Now, you can see that my ping to foo.bar.com goes to not Google Cloud, but to this machine. Here it is, going to this machine, 127.0.0.1. I'll break it, clear it, and then open browser. This time, I'll open two tabs, one goes to localhost, which is still 503, and this tab is going to foo.bar.com. foo.bar.com is now this machine. If I refresh, this is currently showing Google Cloud, I'll refresh and you can see that the result is popping up right there. Go to im, and here it tells you localhost unavailable. What is going on, as you can see, is proxy detects. When somebody is asking for foo.bar.com, so please give me foo.bar.com, the request goes to this machine, the VM where the proxy is running. It asks for the proxy, say, give me foo.bar.com please, so proxy says, oh, I know where you are, let me just send it to this container. This container, when you reach, you will see im, that container. Whereas here, in the other case, when you ask for localhost to the proxy server, localhost, there is no such service running by that name, so it doesn't know what to do, so it gives you this error. That's the scenario that you just saw running in a live example. What I will do now is close this container, at least the browser window, and then go back to our containers, and you will see that we have two containers running, which is expected, and we just finished the first portion of this exercise. By understanding how do you convert a command into a composition like this, a command like this, into the second composition of a service like this, and run both together. Right now, if you see docker rm-f and docker ps-aq, I killed everything that I have, and then this time, what I want to do is go to the step-by-step location, and there, I want to actually invoke this YAML file. That YAML file is, I think, this one. I'll take that YAML file and say docker compose. Instead of saying up, I'll say docker compose that file. I think that's the syntax, but let's go check. I'll say docker compose up, dash f, that file, and dash d for daemon mode. It goes to daemon mode, and I hope it did not work. Let's go see how do you pass a file. A file reference, build, remove, scale, detach mode, daemon mode. Where is the file reference? It's not here in this help. Let's go to Google and say docker compose custom file. Docker compose cli is a dash file, alternate compose file. That's what I typed. That's exactly what I typed here, alternate compose file. What did I do different? First, say docker compose, and then the file name, and then, okay, fine. Sequencing was wrong in my case. We'll say docker compose, and then dash f, and then this file number 1, 1. What's the file name? 1 dash, 1 dash docker compose jbuilder YAML, and then docker file, and then what? Up, and then dash d, and then it creates the whole thing. Now you have two docker containers running like before. There's a proxy container, and then there is the who am I container, both of them running. You can now call localhost. If the font is too small, please tell me. I think it is too small. I'll adjust. There we have control plus, plus, plus. Yeah, this should be a little bit better. What we have now is two containers, and what I want to do is call localhost, and you will see the error 503. There it is. I will call the other way, which is pass in a host header, and ask for foo.bar.com on the localhost machine, and you will see the correct answer. You will get this container ID back, by the way, f33, and there it is, f33 coming back at you. The instruction to instantiate the composition was a little different. It was like this. You could stand up the whole stack by going like this, and that's what I just did in the second iteration of the same exercise. This is the first time I ran this and then that, and next time, what I did is just one line, line number seven, to instantiate two containers, and I'm able to validate and test, and everything is working fine. Now we'll go cross-check our processes and delete them both again. Here we go, docker rm-f, and kill everything. It kills. Having seen that, let's go to the next exercise, the next portion of the same set of exercises. I'm closing out these windows, go to the number two. Here's a slightly longer docker file, slightly more involved docker file. It also has a proxy definition, and it also has a little bit of extensive. Let me expand it. There's a lot of things to read here, so close it. Let me split this one on the right side, and this one, and then this third one, split down. Yes, now this is good. Now we'll inspect what do we have. This exercise is conceptually similar to the previous step that we just did, but only in concept. Let's see how they are similar, how they are different in a white sheet of paper. The first exercise we did just now, we had a reverse proxy created, and then we also had a service called whoami. We have a user that asks for localhost. Localhost, there is no such thing defined in the proxy, so proxy doesn't know what to do with it, so it responds back by 03. I don't know what to do with you. The same user asks for who.bar.com. You can do this in curl without having to worry about DNS, or you can then edit your hchost configuration, and then you can use the browser to do the same step, browser, to go to this who.bar.com website in the browser, and then you ask the proxy, hey, can you? It will show you this because this thing advertises itself to the proxy that I am who.bar.com. That's the scenario. That's what we saw in the first iteration of this exercise. Now comes the second iteration, which is slightly more involved. You'll now see it. I'll just quickly review what we have so I will know what we're talking about. We have one, two, three, okay, fine. So what we are now doing is, first thing, we are creating a subnet. Yes, without using a VPC, we are creating a local subnet on Docker. It is called CG or some name, some subnet. In there, we will create a machine, a container called WordPress. Another container we'll create called MySQL. Actually, it will be called DB. It will be running MySQL, but the name will be DB. This will be called WP. It will be running WordPress. It will be called WP. Is that the name I chose? I chose WordPress as the name and DB as the name. So names are WordPress and DB, so it is also called WordPress. So the names are WordPress and DB. It is running the runtime environment is also WordPress and here it is MySQL. And that's on a subnet. We're creating a subnet work in Docker that's called CG. It's an externally created subnet, external subnet name. So having seen this scenario, that's how you create a subnet. So that's the last segment here, this portion. This is a Docker compose file, by the way. And in that compose file, we have three services. What are those three services? There is a proxy service. There is a database service. There is a WordPress service. You will also see that there are some volumes here, volumes. This volume is basically restored database data. So this database data is used here to store the data for the database. So that data for the database called MySQL gets stored in this location in the container. This gets stored in the machine in that volume, which is this, is defined here. And these three services all be running on that same subnet. And so these are the services, one, two, and three, three services. They will be running on the same subnet. This is for simplicity. We have done it like that, just for simplicity. So what I'm also describing to you, sorry, I need to change my ink. And so changing my ink, I need to have another proxy also running. And so then the user can come and ask proxy, hello, can you show me database? And it will be rejected because user should not be allowed to touch the database directly. If the user comes in and says, can you show me WordPress? Then proxy will know that, you know what? Yeah, I need to show you WordPress. So it just diverts the traffic to this container. If the user comes in and says, show me localhost, please. And the answer will be 503, temporarily unavailable. In here, it will be rejected. In here, it will be granted to this location. So that WordPress container will show up. We will go to ask the proxy, show me what you got, and it will show us WordPress solution. Try to access database itself directly, this one. It will say no. Try to access localhost. It will say nothing found. And that's the scenario we are going to see live in this exercise, in the step of the exercise. Having seen this, I will read a little bit here to understand any missing pieces. Let's see if there are any things missing. Probably not. Probably not. But you will also cross-check that we can create these containers manually by running them one at a time. For example, here. This container can be run manually and created like that. Or you can use this service configuration here and have the same container constructed in a Docker Compose design. Same idea here, repeated. Or you can write this in this block like this. So the same thing again, except you also have a network reference, an external configuration network reference, which is what we have already here. The same thing that you have here is already here. This is a combination file. So it contains every single thing that we have on the left side. Now on the other missing pieces that we have, which are not here yet, is the database and the MySQL items in the services in the right side. And so let's go see what we have in the other side to correspond to our services called DB and WordPress. Let's go see that. Here we have a command Docker run something to generate a database and another command to run something to start a WordPress container. So this is a Docker run action. This is also another Docker run action. And then there is the third Docker run action. Actually, that should be the first one because it's a proxy server. You need to put the proxy in place first. And so that is what I plan to do right now is as soon as I clean up my Docker, which I have, I would like to instantiate a Docker container running Nginx proxy. So that my proxy goes up and running right away like that. And here it goes. So proxy is expecting a network CG externally created. We don't have that network here. We need to create that. It is defined externally. And so it has to be created. How do you create an external network? You simply say Docker network create. I think that's the action. Let's go try. I don't remember, but we'll find out. So docker network create CG. That should do it. There it is. So Docker network list and should show us a list of all the networks it has. So there is a network called step by step. There is a network called test default. Those are two from previous attempts of creations of something is in Docker compose. And we have a new network here called CG created. It's a bridge network. So we can do a cleanup and get rid of the other networks also by simply saying Docker system prune and dash F. And so it will kill everything and all the networks are also gone. So now that we don't have any Docker networks that are not default. So nothing and nothing that is created by us. So these are the three things that come with Docker to begin with. There's a bridge network, there's a host network, and there's a none network. It's a null network. It doesn't actually work. It's not supposed to work. It's a null driver. So all the traffic will be going to die. They go there to dry. If you don't want any traffic to go anywhere, that's where you send the traffic to. That's a null network. Now it's a null driver. The bridge and host, the two networks already available by default with Docker. And now we'll create one more called Docker network create and call it CG. That's a subnet created. And in that subnet, what I want to do is create a proxy. So here is the command to create a proxy, nginx proxy. So we'll copy that and go to the terminal and instantiate a proxy. Here it goes, started. Now the proxy is listening, but then there is no other container running, so it doesn't know what to do. So every command that you try to open in the local overload machine, even foo.bar.com, it will fail. It is supposed to fail. So try to go foo.bar.com. It is supposed to go to the local host machine, but it doesn't know what to do, so 503 unavailable. Similarly, go to local host, you'll get 503. Again, that's totally expected. Having seen this, what I would like to do now is see if we can start a database and a WordPress container also. So here we have a scenario. We want to create a database container first. So grab that command. And in that command, you will observe that I'm passing a network reference. I'm passing this network reference here, cg, this reference. It goes to map this network that I created manually, docker network create, cg. So that is already expected to be available, which we now have. And so we'll be able to use that network. We have to have a name that we want to have, so that's the name association here. We have a database mount to the externally mapped folder. That folder, the volume is this one, which is mapping to this location inside the MySQL container. And there are some passwords defined, database and username and password. These details are environment variables. And that is what we'll use to create a new DB container. Meaning we are actually doing this segment. It's the same set of things here. So the environments are the same as here. And the data mapping, volume mapping is the same thing that you have here. Oh, sorry, here. And so that's the relationship. And now that we have understood that piece, we will now create a database container running MySQL database server. And so here we go. And it's now available. It's running. You can see how easy and effortlessly you can start a container as opposed to a virtual machine. And that's the hard part with VMs. This one is running already, by the way, this MySQL thing. And the third container we need, which is a WordPress application. So here is what we want to actually run. However, we need to let proxy know that this thing is normally known as foo.bar.com. And that reference is a virtual host reference that will notify the proxy server that I am foo.bar.com running WordPress. And that's a notification being sent in the environment to the proxy that I am foo.bar.com. And then there are some host references, username, password references. These are the same thing you have here. And using the WordPress image that matches this image. And then you are exposing port number 80, which is what we want to expose. But again, note that we are not mapping the port 80 colon 80 from a WordPress container. We are not doing that. We are doing this action here for proxy, not for WordPress. That's the thing I want you to pay attention to, is that we are doing the port mapping but not for WordPress. We are just exposing it to port number 80. We are mapping here, not here. This is just an expose. Similarly, you actually don't want to expose. You don't want this port directly connected to the machine, direct on the VM, on the machine. You don't want it. You want proxy to handle all this customer traffic. You don't want people to come directly to this container without going through the proxy. You want filtering to happen right there before you let them to the application. You don't want the underlying idea behind. You don't map. You map here, not here. This is just an expose to that. It knows that I am known as who.bar.com. That's the declaration coming from this container shown here like this. With that seen and understood, I will now erase my ink again from the container command execution and run in the command line like this. Copy. Go to the command line and run. Now we have another container. Let's go see what we have, Docker PS-A. We have three containers running already. If you pay attention to the port mappings, you will see what we are talking about. This container is the proxy container. It is correctly mapping port number 80 to 80 from machine to the container. But there is no other port mapping here. It is just exposed. It exposes 80 for WordPress and exposes 3306 for the database. That's where the database runs. This container here we have, it is the database server. It is running MySQL image. It is exposing port number 3306 and also exposing 33060. There are two ports exposed. There is another container here called WordPress. It exposes port number 80 and it runs WordPress. There is another container here. This container is the proxy. It exposes port number 80. This is mapped to port number 80 on the machine side. This is the container side. This is the container, container, container, container. I should maybe write these things inside. That makes better sense. I should write this number 80 actually inside the container. There is no machine mapping. It is just at the container level that we are exposing certain ports. What are we exposing? Specific ports like 33060 and 3306. This is a standard MySQL port. That's what you are to expose. This one is an additional expose done by this image. Now, we have a declaration that we made that im and the name is food.bar.com. That is what we have declared here. That declaration tells this that food.bar.com is that one, this guy. You know, keep in mind that imfoodbar.com so it knows. Having understood that part, now let us understand how these are connected together on a subnet. I am going to erase some of the ink, not all of it. Subperson comes in looking for this. It reaches the proxy through the machine port number 80. It gets handed off to the container port number 80 at proxy level. Proxy knows that you want this, let me give it to you. I will send it to you here. That container runs food.bar.com, which actually is WordPress because you know that is the underlying image. That is the concept. Having seen this concept, I will now erase my ink and check whether these things are working like we expect it to be. How do you check? Well, you can do curl or you can use the browser. So we have this action. Hold on. I think that domain name is incorrect. This domain name should be food.bar.com in this location. It should be food.bar.com. That is the name for that container. WordPress container has this new name or rather this name. I am going to copy that command, go to the terminal and see. You will see what proxy will respond. So proxy says nothing. Why nothing? It should show you something. Open the browser. Check localhost and you should see 503, but what about food.bar.com? You should see WordPress and there it is. You see WordPress as you expect it to be. Nothing different from any other WordPress location or WordPress setup. So I'm not going to repeat the process of setting it up, but you understand it. It's working. It is working with three step-by-step Docker run attempts. The first one was proxy creation. The second one was a database creation. And the third one was this Docker WordPress creation. Now that we have this in three different parts, I would like to break the whole thing down and do it in one shot using Docker compose, which is very, very easy. All we need to do is basically clean up. And so we'll go to a Docker clean up. There it is. And so it kills everything. We have a Docker network LS. You will see that there is a network called CG. We need that. It is supposed to be externally defined. This is an externally defined CG. It is expected to be available. And so we have a network now. So this network will be automatically used by all these three containers or three services, the NGINX service, the DB service, and the WordPress service. Having seen this structure and having had this file ready with us, the Docker compose YAML file, what I will do is pretty similar to the previous exercise here. And I'll instantiate another Docker compose stack using the line like that. Actually, it will be somewhat similar, but a different line. That line will look like this. And it has a different file name. The name is Docker compose WordPress YAML as opposed to jbuilder YAML. It is wordpress.yaml. And that's the one command which will bring up the whole stack. So we'll go to the Docker terminal. We'll check our Docker processes and we should not have anything there. I think we don't have it. We have killed it already. So we'll just say Docker compose up with that custom file. So it brings up, it says file not found because I have a typo. So the typo is instead of one dot, it should be two dot. There it is. That's the typo. So I will copy and go here and paste it without a typo this time. And it will bring up the stack. Still not found. It is still a typo, I guess. So let me type this command interactively. Docker compose dash F and then the file number two dash Docker. That file is available. We have a dot as opposed to dash. Oh, my God. There's a dash here, it seems. Okay, fine. So then we have a dash D option after that. So then it still doesn't run. It's up, I forgot the up part. So we have to say dash up dash D. And now it works. So it created three containers now. So Docker ps dash A. And those three containers are running. And we can, of course, expect to see WordPress. So we'll go there in the browser. And go localhost and find 503 error. And then we go to food.bar.com and we see WordPress coming up. That's the idea. Having seen these ideas, what I will now do is further extend the exercise and make it involve a lot more containers just to simulate real-life scenarios. And so that's where I'm going right now, is I'm going to close out these windows that I have open and close and close. And then what I will do is close the step-by-step folder and then go to this YAML file here. This YAML file is empty. It is supposed to be empty. It has an instruction written right there, which basically says what to do. And so that's what I will be doing now, is to build a new Docker compose file depending on what this instruction says. So what I'm supposed to be doing here is copying YAML snippets from the example files and paste it into this file and then compose your stack by running Docker compose up dash D. So these example files are sitting here. There is a three-tier WordPress example that you did not see yet. You saw a two-tier WordPress example. And so what I will now show you, in this two-tier WordPress that you saw, there was a database layer and a WordPress layer. So you can also construct multiple tiers. And so this next example, a three-tier WordPress example, is what I would like to grab from here and show you. Oops, I think I made a typo. Unloop, copy that, and take from there and put that in the Docker compose YAML file right here, quickly, like this, and understand what we just did. What we have in this example is a slight variation from the before exercise. In here, we have three containers. We are slowly growing the complexity. We have a location that we are going to build as a simulation for externally stored data. So that you can think of as data or some file system stored away from you in a protected location such as an EMC or NetApp or some other external storage provider. Or it could be cloud storage. We'll get to cloud storage also. But right now, we are just running these exercises locally. So that folder is where you will store the data. This data folder is actually a separate container here which has a Docker file which needs to be built. So we'll build that using Docker compose. And the command is just one. This command will build and run and do everything you need provided you write it correctly. So in this instruction, we are saying you need to build the data image. So it will build the data image using this file. Next is the database container which expects you to have this image which we are using. You can use any MySQL image, by the way. We are going to use the volumes from this container, the data container. We are also using the volume here to store some configuration that custom configuration for MySQL is coming from this portion. And that configuration is going right there inside in the MySQL container. In that location, that's where MySQL expects the configuration to be stored. Any customization of the configuration is stored in that location. And so we are doing exactly that. We are grabbing this and dumping it inside in that location so that our MySQL configuration will be customized to what I want. I want this configuration. So I'm customizing that way. And now I need to erase my ink because it's already too crowded. So I'm going to clear my ink now and then do it again. So we have to examine what our custom configuration is. We'll see that. But that is what is passed along in this location. So we have a MySQL image that we are using, and it's going to create a service called database. It has some environment variables like password and secrets and things like that. Next one we have is this service uses the WordPress image. It is directly exposing port number 80 and mapping it to the machine port number 80 to the container. So there is no proxy in this example. So MySQL, sorry, this is machine port number 80 to container port number 80 mapping directly without using a proxy in this particular example. It has a dependency, and we are linking it to that. The way to read this db equal MySQL, there is a way to read that and understand it. And the way you will express this idea is like this. The idea is that this link reference basically means you call it whatever you like here, but I will call it MySQL. That's the way you read it. I'll describe this in one more way so that you will understand what I'm just saying. The idea here is like this. Let's see the number of times where db is there. So in this location, we have this db showing up in one location here and in another location. So in three locations, we see it. There is a reference in line number 19. There is a reference here and a reference here. The key thing I want you to pay attention to is this db here and that db service name. That's the key thing to remember. What I'm saying here is you can name these db whatever you like. As long as you let me call it MySQL internally, you can name it whatever you like. That's the way you interpret this link syntax. You can call it whatever you like as long as you let me call it MySQL. That's the internal name that WordPress container will know this image as. So you can call it whatever you like. That's the way you think about this example that I just showed you, which is here, two places, whatever you like. Call it whatever you like as long as you don't call me late for dinner. That was a joke. That is an East Coast joke, by the way. It's not so popular in the West Coast for some reason, but I don't know why. That's my American slang usage. I got it. I don't know if you got the joke or not. Oh, I got it. Sorry, say again. I got it. Okay. Most East Coast people laugh at it and West Coast does not. I don't know why, but you call me whatever you like. Just don't call me late for dinner. So having said that, that's the reference here, two places, and you can call it whatever you like, but I will call it MySQL. That's how you reference that container here, this one. That's how you reference in WordPress, and I will call it MySQL. Externally, you call it whatever you like. That's the mapping for WordPress. Next mapping is our file system mapping. Here, what I'm doing is this scenario that we played around a little bit before, but we are passing a Docker volume reference here to that location and mapping it to that location inside this container so that I can protect my data, my files, my pictures, whatever I upload into this location gets saved and protected in this location in my real machine. You see, this is your real machine. This side is real. This side is container. Same with this, at colon at. This is the container. This is the machine. That's the mapping. This is your volume mapping right here. That's volume mapping. That's port mapping, machine, container. Same thing here, colon, container, machine. This folder, which is this folder, is mapped to this location inside the container. I'm just dirty, so let me erase this. This configuration will store that file here. This doesn't exist yet. We don't have that folder yet here, this folder, but it will be created when you run the container and it will store that files here in the container and if we really store it here in that folder, which will be created, it will be called WP-content. You will see that creating shortly as I proceed forward. It will automatically get created. That's where we will be able to automatically preserve our content. Now, this idea about data is a build step. It will build the folder called data. This is the data storage that we are trying to simulate in a high-end storage solution with a very, very tricky setup. There's nothing high-end about it. It's just a container. I'm just using it as a proxy storage for external storage. Imagine that that's the container that I want to create using the folder here called data, which contains a file called Dockerfile. That file is what I really want to build. When I say Docker Compose up this line, it will build the data folder which contains this file on the right side, which is just two lines, three lines. It begins with Ubuntu as the basis. You can actually use any operating system. Actually, I'll just use a simpler one. We'll just use BusyBox. Yeah, short, simple, and quick. It will expose a volume, which is what this location will be exposed from that container and will be used as the data storage location. That's what MySQL will be using here is the volume from reference. The volume from reference is basically a reference which this container will refer to that container and store using that volume exposed from that image, which is going to get built when you run this instruction. The first thing you will see is this data container getting built. Then it will create a container using this action. Then it will run the true action, which is returning a success value, return zero, and so it exits cleanly, exits clean. When it exits clean, it leaves the space for the container. The volume is exposed and is left behind. We are going to use that here and use the volume for the database server called sdf, sdf, sdf. You can call it whatever you like. That will be using the volume exposed by this container which exits cleanly. We'll also have another volume which will store our configuration. We need to now see the configuration itself. We haven't seen it, so let's go see the configuration. The custom configuration I have, if I split it down, you will see that it's also a simple configuration. Let me just open it in the right spot. Splitting it down there. This custom configuration, what it does, it allows MySQL to listen to any address as opposed to only local host. That's the only configuration change I'm doing is to allow this container to access that container. It's a different container. MySQL by default will listen to only itself, nothing else, no other box. You have to let MySQL know that I will be connecting to you from a different machine, a different container. Please let me come from any location I want. In a typical Kubernetes deployment, you will narrow this down. This is like whole worldwide internet. You need to narrow it down to 10, 0, whatever subnet you're using, flash 24 or something like that. Whatever subset you use, you will narrow it down to that bind address and then shrink the exposure thereby. Right now, I'm just going wide and it's all full internet, but nobody can actually reach this machine. This is inside my home network. It is actually inaccessible. I don't pay too much attention to it right now. Having seen these ideas, what we are really talking about in a quick short summary is that we have this command to run, which will build this folder, which contains this Docker file. I just changed it a little bit, doesn't matter. You can use any OS image. It doesn't really matter what OS it has as long as it is Linux. Then this container will create and exit successfully. We'll leave behind this volume. We're using that volume here. That's what MySQL will store the data at in that location. It has a custom configuration that looks like this. It allows it to connect not just to itself, but also from another container like this one wants to connect to the MySQL container. It will allow this rule, custom configuration rule, which is stored in that location inside this volume, which is actually stored in here, that location that is here. That's what allows this to connect to the MySQL container because of this expanded binding address. Without this, this container will not connect to that container. Access denied, MySQL unable to connect, and all the errors will pop up. The last bit of information here, which is that we will have a folder here created, wp-content, that will store the images and anything that you upload into WordPress here into the container will automatically get copied over and protected in a real machine. This is container. This is the colon in between. That's the idea. Now, having seen this inking, I'll erase my inking again. Now, we are ready to bring this up. Close the Docker file, close the custom configuration, and leave this Docker compose YAML open, but that's the command to run. Before we run, we'll just check what do we have running right now and kill it. There we go. We killed everything. Nothing is running. Let's go to the browser and try localhost. We'll have unable to connect, and there it is, unable to connect. Now, we'll go to the command line again. This time, we had to come out of the step-by-step folder because we want to actually use the Docker compose YAML file, and we want to run this command line number four. Docker compose up, and then dash D option. You will see now what's happening. It is going to build an image using BusyBox. It pulls, it downloads, and then it creates a volume reference, and then it runs the true action, and it finishes. Next thing is that it is pulling the MySQL image, and then it is pulling the WordPress image. I think WordPress already existed. It created a MySQL container, and now it is creating a... I think it just did its thing. As a consequence, you have WordPress running, you have all these things running. Let's go check what is running right now. Docker ps-a. We have three things running. Actually, two things running. One is done running. One that is done running exited successfully, and it is Docker files data, that data container that was built here is this one. It exited successfully. It has done its job, and it is built using the build step. We also have two containers running here, MySQL container. It is up. It is exposing port number 3306. That's where MySQL runs. By the way, 3306 is the port number for MySQL database. This guy is mapping its port directly to the machine, the container port number 80. That's the mapping you can see here. That's where WordPress is running, which means we should be able to see WordPress now. Let's go to the browser. Here, what I want to do is open up, and I will clear my ink. Here, I clear the ink. Localhost, you show me what you have. Here, we open localhost, and we get WordPress. This time, I want to actually fill it up, and fill up with something that will show us data protection. Here, we have a title, Cloud Genius username, password123, and confirm the use of weak password, which is not a good idea, but I just want you to know that I'm using a weak password. This is irrelevant. Internet cannot come here. Google cannot search my machine, so it's not possible, but I'm still telling you what should be done in a real setup. Discourage Google from indexing unless you are ready for it. I install WordPress. You will see that it is the latest WordPress already running and available to us. We just log in, and here we are inside, and I should type properly. One, two, three is my password. Did I type one, two, three? I don't know. One, two, three. Yes. I type without looking at the keyboard. That's the reason why. There is a new update available. Oh, man. Okay, fine. Update now. It's going to update. I'll say, okay, go update. It's going to update, and it doesn't hurt. Installation failed. Could not create the directory. See, there are some permission issues. We'll deal with the update later. Let's not focus on updates right now. Let's go focus on what we can do with it. We have the data called Cloud Genius here. Let's see if we can upload a picture. Let's see that. We have to go to the dashboard and see if we can get to a media, and can we upload a picture? Select a file, and the file I want to send is GIF container. That's a big fat file. No, that's too big, but I'll still try. It exceeded the maximum size that was expected. Let's see if another thing they're going to upload, maybe a simple text file. Select a file and upload some file here from recent, maybe here using Chef Solo. Yeah, let's upload the Solo RB. Yeah, open and see what happens. This type is not permitted for security reasons. Oh, my God. Okay, this type of file, Ruby file is not permitted. Let's go see if we can upload some other file. Well, we don't have any picture in the machine, so I'll go download some picture. How about this picture? We'll download some picture we should have. Yeah, that picture is good, so we'll save it. Come on, come on, come on. Oh, it's running all over the map. Let's grab one of these pictures here. Copy, save image as, so that's an image. Oh, it's SVG file. Oh, my God. All these files, I have an SVG, and they're not considered supported in WordPress, so I'll grab this picture. Maybe it's not an SVG. Okay, and so save Nilesh and save in downloads. So now I have a picture available. Okay, great. Let's see. Now this one is allowed to be update uploaded. So I will now grab the picture, add new, select file, go to downloads, and see if this picture goes up. Not writable by the server. So this is the same issue, right? So let's go identify how do we actually solve this writability problem. So this parent directory writable by the server, so that's the thing I want to confirm what is actually causing it. So what I will do now is check our Docker processes, go to the WordPress container directly, meaning Docker exec, IT, and then 005 is the number, so 005, and go to bash prompt inside. Now here we have a folder called wp-content, and there we see the problem. The problem is that this folder, wp-content, is owned by root as opposed to www-data. So we need to change that ownership. How do we change? We say chon-r www-data, and the folder is wp-content, and this should change the permissions. The permissions are now set correctly. Now we'll exit out of the container. This permission, you can actually handle it automatically also. I needed to go inside to hack the permissions, but you can actually deal with it in Docker Compose or your Docker files itself. So the permissions are automatically set correctly. Having seen this portion, let us now try the upload or refresh, and upload one more time. So here, dashboard, media, add new item, select a file, nilesh, open, and there we go. Nilesh is now available in the WordPress. This guy is now available. It's a URL for nilesh, so we can go and copy the URL, and it is openable in this location, so we can just paste it, and it shows nilesh. Awesome, it worked. Meaning this file got uploaded to the container, which means our action to upload, update WordPress should also succeed. I think this should succeed. So say update now, and it is updating. So it should update. While it updates, let's go see what happened to the picture. Where did the picture go? We uploaded this nilesh picture, and we have a plugin to update. The plugin got updated, and WordPress got updated, and the whole thing is now up to date, and there are some themes also up to date available, apparently. They are selecting some themes to update them. They should also work. There is no reason for them to not update. So I think everything got up to date. We can see the site. We can see our images and media in our dashboard, and you can see that this media library contains one image, which is this guy here. We can see where this file actually sits. We can go to our terminal and go inside the container. And in the container, we have it right there, and we know that the location is slash VAR www.html, and then we know that the actual location where the files get uploaded is the wp-content folder. So we'll go inside wp-content, and then there is a folder called uploads, where the uploads go. So here is uploads folder, and then here we have 2019 folder, and then a February folder, and then we have nilesh, and that's the guy. That image is what I uploaded. There is a smaller version of thumbnail got created that is stored here. So these two files are stored in a location called wp-content upload 2019.2. So that's what we have inside the container. But what about this thing? We know that this location is mapped as a volume reference to the local system in that folder, and that location happens to be right here, which means we can see uploads and 2019 and 2 and nilesh. This came up in the local computer, which means we can totally destroy our Docker compose setup here, whatever we have, and say docker rm-f docker psaq, and you go away, it is all dead. So now nothing is running. You can check that this site doesn't show you anything, unable to connect. You can go back here and look at our Docker compose YAML, and we just say Docker compose up one more time, like that, here, here, and say Docker compose up. And it brings up the whole stack, and it's now up and running, and not just running, it is up and running with your data intact, like that, with picture of nilation, everything. So let's go check what's going on. Why are you not loading? Well, it is booting up WordPress. Made a mistake, made a mistake. I made a mistake. I lost my data. That's what you should not do. So that's the reason I want you to highlight. It's a good mistake. It's a good mistake I did. But that will drive home another point. Okay. So the point was that I shouldn't have cleaned up completely left and right. I should have preserved this data store. And I did not. I killed everything. But I didn't, because I did not pay attention. That's a bad thing. So do as I say, not as I... Yes, yes, yes. So what I was talking about is the data is stored here in this container, and this is supposed to be an enterprise-grade storage, which you cannot just kill by running a command. But I did. And so that was a mistake. But it's a good one that actually helps us understand what happens. So with that understanding, what I will actually do this time is to next time when I clean up, I will not kill that container running the data. If that thing dies, then you're dead. Then your data is lost. So we should pay attention to actually store that data in a real, physical, protected storage, not in a container that will disappear like a command with a command. So that's the point. Having said, let's fill it up with data one more time. So let's go back to our WordPress. And we'll just fill it up quickly. And I will also delete these pictures. And I cannot delete now that permissions are different. So I have to go and check the permission structure and kill that folder. So it is going to be WP content and then uploads. That's what I want to kill. So sudo rm-rf uploads die and the password is clubgenius. So it's one step back. And now we have our Docker processes running and our login working. And now we'll upload a picture of Nilesh. So it is an update available. We can update that successfully, I think. Update now. And then we'll add a picture. So update is happening and updated successfully. We'll now go to the media library and add a media item there, Nilesh selected. And here is the picture going up and picture went up. Then we can finish off our upgrades on the dashboard. And so go to number four and update this plugin. And then we'll also update our themes. There are three themes to be updated. We'll go to the updates, select all the themes and update them. And so now we have a completely up-to-date system. With that in hand, what I would like to do now is to kill the containers this time carefully. So we have our media and everything in good shape. That media file, by the way, is again available here. We just killed it. It has now come up again. There is a picture of Nilesh again saved. And that is that picture of image is a picture of Nilesh is available. The smaller picture is also available. This is the full picture and a reduced size picture. And those two are protected in the real machine here. What I'd like to now do is to actually carefully delete only two containers. So here I will widen, check, and carefully kill the WordPress container and the 8A container. So the 00 references the WordPress container ID 00B3. You don't have to type the whole thing. Just initial few letters are good enough. As long as they're unambiguous, it's okay to use just 00. And this one I want to kill also, which is 8A. But I do not, absolutely do not want to kill this one. So I'm not touching it. That's protected by the enterprise-grade storage. So think of it that way. And you actually, when you deploy it in a company, that's what you actually do. And so this cleaned out, which means we have one container, that one. And our site is not functional. So go up and it's unable to connect. Now what we need to go back here do is just Docker Compose up one more time. Now it is running and we're running with everything intact, every single thing. Let's go load. And it says WordPress database required because this is the 5.1 kicking in. We just updated the WordPress database. Actually, it was already done. So it did not do much. It was already up to date. And so here, again update. You see something happens. And I would like to point out how WordPress behaves a little bit different. What we are doing is that you see this update now action expected from us. But you see the media file contains our media image and that is still there. But updates and plugins are not apparently protected. Can you tell me why that happened? I expected, incorrectly expected, updates to also preserve. But that didn't happen. Can you tell me why it did not happen by looking at this line? And also a folder I would like to show you so that you will know what is going on. The folder I would like to show you is inside the container in the WordPress container called daf0, that one. That container. I'll go inside that now. And here you will find the folders. And you can now tell why upgrades to WordPress and the theme and plugins were not protected. But only the picture got protected. See the picture is still there. But updates are not preserved. I still have to update. I can update. It's not a big deal. But when you're talking about protection, you protect the whole thing. And I did not. Apparently, that's what happened. So I still have to go and update. But why, what did I do that is not complete in its capture of the state of the application so that it should have preserved the updates, but it did not. So what happens and what happened and how do we correct that is the point I want to discuss now. So you saw that updates were not preserved, but the image was. And the login information, the cloud genius, that detail about cloud genius here, that is preserved. The login name, password preserved. My name preserved. My picture preserved. But updates? No. So why did they not get preserved? That's the question. So now let's pay attention to what are we actually preserving. So if you pay attention to that, you're preserving that data in this. So that's a database data. The name cloud genius, the name Neelesh, the password 123, the login name Neelesh, like that. That's stored here. And it is protected in that location. I managed to not delete it this time. Awesome. The configuration is protected here. This WP content is protected here. And by the way, this is just one of the several folders that WordPress uses. What about these files and these files? That's where the updates are. And so that's where updates actually get saved. But if you pay really careful attention to this idea, you will identify a couple more interesting things as I walk you through. You really understand why did I bother to save only the content folder and not all these things. Like here, I protect only the content and not the other things at all. Why? That's what I want to pay attention to and help you understand. How do you think about these things? If that was really necessary, I should have protected these and these files also. But I pay attention to only this one folder because that is the real useful folder for users. Users' data gets protected only in that segment. Anything else apart from this is either configuration or source code. Having seen that idea, let us also see what else we have in our WP content folder. There are plugins and the AKSmet plugin, which I apparently updated. There are themes, and these are updated already. As you will see when I go here and try to find the updates and check again, you will find that... Let me install these things and let's see what actually comes up. Let me get the update. Let me get the update now. You will see that this update is coming from 5.1 from WordPress.org, and it is getting expanded and loaded up. Now you see the updates available to me is the AKSmet anti-spam plugin that I need to update, which I did. There are three more updates for the themes. These themes are one, two, and three. Update them, and they are going in and up to date. Things are now up to date, but the discussion that I want to have is about what do you want to preserve and don't worry about preserving. That's the thing I want to talk about briefly. In this location, you see that I mentioned that the WordPress user-generated data is stored in this location. The configuration is stored here, and everything else is source code, source code for WordPress. The best place to store code is the image, not external folder. If you want to change the source code, you change the image ID, which means I don't want to protect this source code in a folder like this, but instead I would rather keep this in the image directly. The user-generated data is something that I want to keep track of and actually protect it very carefully in an externally mounted storage, especially in a high-end storage for a corporate usage. This piece should actually stay right there. What that gives you the ability to is to use a systematic method to roll back to version 5.1. Now, I don't like it. Maybe go to 4.9. Yes, that is possible, simply by choosing a previous tag for WordPress image. By doing that, what you're doing is you're excluding all these files and let the tag manage which versions of software that you want to get. You want to grab and copy and use, and you want to keep track of that source code for the application by using the appropriate tag image ID for the image being used and keep your user-generated data protected like this. I'll show you a couple examples on this before I proceed forward. Here is your... Come on. Why is it not changing my screen? Let me see if the keyboard is not working. Yeah. Sorry. The keyboard died on me. Give me a second. I'll just change. The keyboard dies. No battery. Without warning, it dies. Okay. I have a new keyboard set of batteries coming in and just swapping them out. Just a minute. I'll resume forward. This keyboard just stopped behaving at all. Okay. Okay. The keyboard is back. What I was going to show you is the image sources. Is it full screen or what? No, it's not full screen. Why is it not responding to me? Yeah, there. That's the browser I wanted. Here in the browser, you will see that in Docker Hub WordPress, you can actually for any application, you can select the corresponding version for an application by going to the tags. Here is a tag for version 5. Here is a tag for 503. You will notice that there is no tag for 5.1 yet. It's going to come. If you do a Docker pull, it pulls the latest available tags. The latest available tag is 5, php50, 503. You can keep scrolling down to find out the latest tag and it is not 5.1. However, it looks like WordPress.org just published 5.1. This is available. I think the last time we saw it was 503, but now we have 5.1 available. Source code is available, but the image tag is not up to date. That is why it is asking you to update. Otherwise, it should just automatically bring you the up to date version and you don't have to manually update WordPress when you run something like Docker pull WordPress 5.1. It should pull that image. It doesn't exist. That's the issue we are running into right now because it is so fresh that I think the last time which is yesterday when I saw WordPress was not 5.1. Today, it is 5.1, but the tags of 5.1 are not available yet. Somebody is going to create that tag pretty shortly. It's not somebody, some machine is going to create the tag pretty soon and you will see that a new 5.1 tag which is currently not found will become available tomorrow, probably tonight. It happens automatically. The images get built automatically and they get pushed to Docker Hub automatically. That's what will happen eventually because I think this is a fresh case of an update. You don't have to worry about these software updates because what you really want to focus on is here, the tag number, and get the correct tag applied to your application version. You don't have to worry about these files at all and also about these other files. You still have to worry about the user-generated content. That is the primary idea I want you to focus on is that I kept track of the WP content folder and not the whole folder. I could have just said, you know what, map the whole thing and strike and just call it whole thing like that. I could have done it that way, but I did not because you should not. There is no need to. You could capture these images right here like that. Now, that image is not available yet. We can go 5.0.3 or 3. That one is probably available. We can just try to pull this one, which we already have. We try to pull that image. Docker pull, and it will pull. It will say already exists and whatever. Maybe some pieces are missing, so it is pulling. It will complete. That's the latest image available as of right now, which is fine. You can protect the whole thing like this, but you should not because let the image handle the source code, not your file system. There is no need to. You should just keep it like this. You can tag the way you want. Tomorrow, 5.2 comes along. You should just change your tag and update your stack. That's it. You get a fresh update. You don't even have to go to the browser to go click this button to get the update because it is kind of boring to go to the browser and say, hey, update this and update that. Just get the new image. That will give you the appropriate version already. When you go here, you already get the latest version. There is no reason for somebody to go log in and manually click a browser window to get the update. That is not how you update. You want to get the latest version of MySQL, just change it to that number. Then you run the stack. That's what gets you my 5.7 version of MySQL. Let's go see what is the latest version of MySQL available. It is the tag version, 5.7, 8, 8, 0, 15. I think that's the latest. We can grab that version and 8, 0, 15, grab it like that and drop it in right there. Test it out and see if it works. If it works, you roll into production. This one is not working, but this one, this 5.0.3 is. We know that one pulls. This one also will pull. Let's go check the pull first. We'll go check here and say docker pull that one. It will pull the MySQL image 8, 0, 15. We have 5.0.3 already for WordPress. We have a new stack now. We just update our stack. That's the way to handle source code, not manually updating the applications. Just keep track of user-generated content and let the application handle it through image, like line number 22 in our Docker Compose YAML file. I'll just test this new stack out and see how it responds. We'll figure out what is working out. Maybe that new version of MySQL is not supported or may need some configuration change. I don't know. I haven't tested it, but I'd still like to play with it. I'm pulling MySQL 8, 0, 15 right now. Once it pulls, then I have a new image. What I'll do is docker compose up again. It will just recreate the new stack using the new images. Here, recreating this and recreating that. It has created some SDF, SDF because apparently the name was SDF, SDF. That's okay. That doesn't matter. We'll just see if this thing still responds and apparently the correction of the reset. Something did not work. It did not work the way we expected it for some other reason. We had to go check the logs, but that's debugging scenario. We are not doing that right now. We can check Docker Compose Logs to give you the logs of what is going on. What is going on and apparently MySQL is shut down. MySQL doesn't seem to like the syntax. It failed to initialize the storage engine. This 803 version was not very compatible with my current setup. I should go back to 5.7. I never tested it to 8. That's why it did not work. We just set Docker Compose up once again. Now we have an older version of MySQL that we know works. It will now synchronize and recreate the stack. We'll check the logs to see what's going on. We see the stack is probably functional. I think it is functional. Let's go check and load. Then we have the stack ready. You can log in. Where's the login button? Here. The login should work like one, two, three. There it is. It is up to date already. That's the scenario that I want you to pay attention to. Be very careful on what you want to really preserve. You don't unnecessarily preserve and protect things that should not be protected because the right way to protect is not a volume mapping, but keep track of source code in the image itself, in the image. Don't try to protect WordPress software in a local file system. That's not a good idea. Leave the applications running in the image. Get the user-generated data outside and keep that in track. This one will change tomorrow to 504 or whatever it does. You just come back here and change the tag. Now we have 5.1, but the image is not ready. We cannot do it right now. Let the image form first. Then you change this line number 22, save it, and say Docker compose up. It brings up the new stack with a new image. You have new source code, but still, your content remains the same because it is externally protected here. That's the idea. Having seen this concept, let's close this window and actually get rid of these things that I added because that was a copy-paste from another file. I'm going to get rid of this, but before I get rid of it, I want to bring my stack down. Docker compose down. We'll bring the stack down. That's another way to bring it down. Another way, hardcore way is just Docker rm-f, and that's another approach. You can see that the Docker already shut down the whole stack, so it is gone. Having seen that, I will now clear out these items. Now we have nothing. We copy-pasted this from here. That's where I got it from. You can assign labels like this or not, but that's where I got it from. I will kill it now. Now I have an empty file. I will take the next example in this concept. What I would like to do now is I'll begin with a set of examples that uses the NGINX proxy and a bunch of things. This is like a huge party of containers, lots of containers, different containers, all participating, all behind a proxy, and they have different names and all that good stuff. That's the underlying concept. It's a little long example, so I like to simplify it for you. The way I will do that is to draw a picture. Let's first of all take a quick look at what this ComposeYAML file is. It's a very long one, but let's go copy the whole thing. Copy from here and put that in the first empty file that we had, which is Docker ComposeYAML, and paste and save. While copying and pasting, don't make a mistake in indentation because this is a YAML file. It will cause you serious heartburn if you make an indentation mistake. Please prevent that by being careful. What I'm doing right now is just shrinking the whole file font to a manageable size so I can see the whole thing in one shot. No, it's too small for you to read and fit the whole thing in one shot. That's the hard part, but let's not focus on reading this, but instead focus on what I'm going to draw right now. The ideas that we have to discuss right now is that there is a user. The user wants to connect to a proxy. Behind this proxy container, there are a bunch of other containers running here. Like that. Any number of them you can have. Each one of them have a name, C1, C2, C3. They have a name like that. Like this is a C1 container. This one is running here. This is a C2 container. This one is running here. This is a DB container. This one is not connected directly to the proxy, but it's actually used as a database storage for this WordPress container. This container will use the database storage on port number 3306. It will expose itself on port number 80 to this guy, and the proxy will export itself to the world outside on port number 80. This guy will also export itself on port number 80 to the proxy. It is called C1. This is called C2. This one is just a data container. The data container is connected to the database where it stores the data, just like the previous example we saw. This is very similar to that. We had a three-part example, one, two, and three parts. That's the same story here in this picture. We have another container here running something else called Joomla, another open-source software that's running in C3. It requires a database though. What we are doing is saying, you know what, we already have a database, so just use that one. Then let's see what else we have. We have a bunch of things in this. I have some to scroll. I will scroll quickly and see what we have. We have Redmine and PG. We have one more container. This is running Redmine, which is a CMS system. That requires another database, but it is not MySQL database. This one is MySQL. Redmine requires Postgres SQL, so not this. It cannot just hook up to the same. We have to have another container running Postgres. Then it connects to that database, different database, PG. This container runs and connects to that. That container has a port exposure 5432. That's the number, port number 5432 is where Postgres runs. This container runs on port number 3306, and Redmine is an application in the open-source running on the C4 container that connects to the Postgres database. That's the setup. Now, having understood this design, the point of this design, if I will redraw the whole thing, is like this. You have a user that asks for, hey, give me C1. The proxy will divert the traffic to C1. User says, give me C2. Proxy will divert this to WordPress, which in turn is connected to MySQL, which in turn stores the data in a data container. Then the user says, give me C3. It goes to C3, which runs Joomla software, which expects MySQL. But we are not creating a separate MySQL container. We are saying, you know what? Just connect to this. Sorry. Just connect to this. What am I doing? Just connect to this, not a separate container. You can do it that way. But since containers are so easy to start, it's actually a better idea to not go like this. But instead, give this guy its own separate MySQL and its own separate data storage. That's a better design. But you can cheat and go like this. Technically, nothing is wrong. Practically, you should do it this way, separate. When you're dealing with a third-party customer outside, it's a good idea to keep them separate. Just because you have this customer and that customer, two different companies, one wants WordPress, one wants Joomla, you don't want to miss their databases in one. That's a bad thing. You can still complain. Nothing is wrong technically. You can still keep them separate. But as a good idea, let me go here. As a better idea, a better idea is to have the user asking for C1, C2, C3, C4, whatever they ask for. You give them that, but the C2 comes into the proxy. You give them a container which happens to be WordPress, needs a database, needs a data store. You give them the data store like that, and that's the connection to C2. As for C3 comes along, you run a Joomla container that needs a separate database. You could actually create a separate container for them and a separate data store because it is cheap and efficient to create a container quickly for a different application. You could actually do it like this. This is the right way to do it. But in my design, I'm cheating. I'm doing the way I would want to not do, actually, honestly. Because in practice, you should do it like this. The reason I have an example that actually includes both scenarios is to just highlight the fact that you should not do what I'm showing you what I'm actually doing, meaning sharing databases across two different applications. You're sharing database servers. You can, of course, create a separate database here for WordPress and a separate database here for Joomla, and that is totally manageable and totally easy to do that, but it gives your customers a better sense of isolation between this and that. Just give them a separate container is a better actual practice, practical idea. Practically, you should keep them separate to give this clear idea to the customer that they are actually separate and there is no cross-contamination. Let's just give them a warm and fuzzy feeling about it, which is a good thing, which is what you really want, actually. Give it this way is what you should actually create. Having described this idea, I am not doing it this way. I'm doing it the somewhat impractical way. Let's be clear about this. I'm actually doing it like this, but it's just a tweak. Just add one more block to the YAML file and you have a separate container. There's no big deal as such. All you need to do is grab this segment for the DB segment here. Let me make it a little bigger. In the C2 container, we have the C2 container runs WordPress. It needs a database, so database container. It has a data place to store data, so that container. These two containers, just duplicate them one more time and make it available to the Joomla container because it needs a DB. Just give it a separate DB, but I am not doing it in this example. I just want you to know that. I'm not doing it because the real reason is that I want you to succeed with the exercise. If you're running too many containers, you might not. I might succeed, but you might not succeed because your RAM has limitations. You cannot run practically lots of containers if you are constrained on a VM with only so much amount of memory. That is one of the real practical reasons, practical for me to shrink and merge them together to get to a working setup. The correct way to set it up is not this, but to have a separate database container, just like I have in this illustration. Not like that, but a separate DB and a separate data store for every application. Keep them separate. I'm not doing this here because if I do it, I will succeed, but if you try to do the same thing, you will probably not, primarily because your memory limitations. You will typically have 8 GB RAM. That's what I observed. Maybe you have more, but I don't know. I cannot assume that everybody in the program has like a 64 GB memory machine like I have. That's not an assumption to make. It's not a good assumption to make. That is the reason, the real reason why I am cheating, but I need to cheat. Therefore, I am cheating. I need to cheat, so don't. I need to cheat because I told you the real reason because your memory is probably 2 GB or 4 GB or something like that on the VM. I have, I think, 26 GB. I just showed you. Basically, it lets me run with a large container infrastructure on this machine, but I cannot assume that everybody has the same setup. That's the reason why I am a little bit cheating in this example. I just want you to know that. Having said, I will now run this. Now, we will talk about what this means from a practical usage perspective. Why am I doing it this way? We'll soon take this exercise to the cloud and to some cloud and we'll run it live in the cloud setup also. Now, having briefly talked about this container, I will walk you through on the Docker Compose YAML from top to bottom in slightly bigger fonts so you will see what is going on and then we'll run it. At the top, ink. First container, nginx-proxy. Maps the machine port number 80 to the container port number 80. There is a specific volume mapping expected by nginx-proxy and that allows it to listen for the Docker socket. That's the mapping here. Listen to the Docker socket like that. It knows what other containers exist. Otherwise, this proxy will have no idea there is C1, there is C2. It will not know. This mapping allows it to read the Docker socket for other containers so that they can advertise themselves as virtual host, C1. Virtual host, C2. I am C2. I am C1. It needs to tell this nginx-proxy through the Docker socket, and that is the reason for this volume mapping. Next, this container, C1, is a standalone container, all in one. It's for demonstration. It's not good for production, just for demo. That's this container. It runs WordPress. It has MySQL inside. Then it's a bad way to do things. Just calling it out. This is a bad way to do things. Don't do it this way. Just want you to know because, again, I'm doing it to illustrate a point on how you should not do things and how you should do things. By the way, I will also show you how to do things the right way in Kubernetes exercises, which is coming up. A few days down the road, maybe a few more sessions down the road, but we have it. It's already available for you to review, if you like, ahead of time. That's the right way to do things, not these. These are concepts you're understanding, what is good, what is bad. I'm giving you the flavor. This example implementation is a demo, not good for production. That was just this container. It advertises itself as C1, so the Docker socket knows, and then nginx-proxy knows that C1 is this guy. It is exposing our port number 80. There is C2. It runs WordPress. Expose on port 80. It has a password. It advertises itself as C2. The name is C2, so that proxy will know that I am C2 here. I'm clearing my ink again and scrolling. You will see that the C2 guy needs a database and a data store. A place to store data is here. The database container is this one, very similar to the previous example. This is your WordPress container called C2. It links to the database container here. This stores the data volume in this location, which is built from data folder, which is that one. That was about C2, its database, and its data store. This is running WordPress application. I'm clearing my ink now. I'm scrolling to the next one, C3. C3 is a Joomla application. It is conceptually a content management system using PHP, MySQL, and RampStack. Same thing, different application, Joomla. This is the image. It links to the other database that WordPress uses. This is the cheat route. I'm cheating because I wanted to succeed for you. Otherwise, I would have a separate database just for this Joomla, just like I have a separate database for Redmine, C4. It advertises itself as C4. This one says I am C3, and it is C3. This one says I am C4. It has a separate database called Postgres Necessary. I got cheated, but then cheating doesn't work because the database itself is different. It's not MySQL. It needs PG at the end of the file. Having seen this file, I will now invoke the Docker Compose action. Let me close this window and go to Docker Compose and say bring up the stack. Before we bring up the stack, we check our Docker processes are dead, and our browser shows us nothing. So opening the browser and say local host, unable to connect. Now, if you ping C1, what do you see? Nothing. It goes to my Kubernetes cluster. So bad idea. I don't want it to go to Kubernetes in Google Cloud. I want it to go to this machine right here. So what do I have to do? Edit my host file again, like this. The password is cloudgenius. And here I am doing another hack, DNS hack. I'm saying this is my C1, this is my C2, this is my C3, C4, C5, like that. I'm just adding a bunch of random numbers so that I can refer to these numbers as my machine. What does that do for me? I can ping C1, and it pings the local machine. Local. 127 001, ping C2. Same thing, like that. There are no sites on C1 and C2, so I cannot go to HTTP C1 and HTTP C2 right now. Like that. Nothing opens, unable to connect. Try C2, unable to connect. Try C3, unable to connect. That's expected. Now I will Docker compose up. My file, docker-compose-yaml, contains all the things I need because I copied from the main examples and dumped into that file. Now that file name is the correct name by default, docker-compose-yaml. I'll say docker-compose-up-d and it begins pulling Postgres SQL because it doesn't exist here. PG is getting pulled. Then it will pull Joomla and Redmine and WordPress already have it. MySQL already exists. That will bring up the whole stack. Proxy already exists, nginx-proxy. We have all these components already available except this PG was not there. Redmine was not there, so it's going to pull them. Then you have the whole stack coming up pretty soon as soon as this pull finishes. You can pull ahead of time if you're doing something in production. You can just pull it ahead of time. In the cloud, these pulls are very fast. You can see that it is downloading some bad image that I call it bad. This is a bad way of running WordPress, Tutum WordPress. By the way, this Tutum thing is the name of a company that got acquired. Tutum.co was the name of the company. Right now, cannot find the server. They got acquired by Docker. Tutum company got acquired to become the Docker cloud. Docker requires Tutum. Tutum means attitude in what language is that? Turkey, Turkish language. Attitude, Tutum. It was a Turkish acquisition. Tutum got acquired by Docker and it became cloud.docker.com, which ran Docker Swarm. What has happened over the years, it's not actually years, just a few years, two years, is that let's go see what happened while it still pulls. We'll go to Google Trends and find out the trends and the trend for Kim Kardashian and Taylor Swift. No, not really. Google Trends. That's what Google is suggesting me. Search for Kim Kardashian. Here we go search for Swarm. We'll compare these two terms and you will see what has happened in the past 12 months. What I was talking about, Tutum. Tutum got acquired to Tutum.co. It became Docker cloud using Docker Swarm technology. Swarm is dying. Blue line is Kubernetes. Swarm was going up and down. Now it is like half. It is shrinking. It's a downward trend. This is an upward trend for Kubernetes. That's the search term comparison between Kim Kardashian and Kubernetes and Swarm. That's the trend comparison as you see. That basically means that this technology is not popular anymore. I have exercises on that one, but then this happened. What I have done over the time is I stopped doing these exercises and I have focused on this. That's what's happening. People are taking up Kubernetes. It is gaining popularity left and right. It is beyond question. In my mind, I'm not bothering teaching people about this technology. I have exercises. You will see them. I'll mention something like this is deprecated. I have the exercise. You can see that I have it available somewhere. Maybe this one and here. Kubernetes has won the war. This exercise is now deprecated. It might work for you, but I will not run it because it is kind of beating a dead horse. It's not dead. It works, but I don't want to beat the horse or whatever that phrase is. Horse or horn. I don't know what. Some phrase. Just American slang. More of it. I don't hear Swarm in my circles, but I do hear K8S. Yes, totally. Totally. Swarm used to exist. Swarm was a Docker native product. Kubernetes has won the war. You don't hear Swarm at all because it's a moot point. We have it. We have exercises, but you can just skip them and go to Kubernetes. That's what the trend shows right here. That's what's happening in the industry. Do what the industry wants, not what you think they want. Find out. That Tutom thing, by the way, this Tutom that downloaded is one of the Tutom images. Now we have the whole stack running. Let's go see what we have. Come on. I type all the time without looking at the keyboard. That's what happens. I suddenly start typing random things because the keyboard moves a little bit. Now let's see what we have. We have a whole host of containers running. Let's understand what is running. Pay attention to the detail here in terms of the drawing I will be making as well as the Docker PS listing here. On the user, he can ask for C1, C2, C3, C4. We have four containers primarily. C1 is actually a WordPress container, but the bad way of doing WordPress, bad way, the Tutom way, the demo way, this is the bad way. Don't do it this way, but it's just a demo. That's just all in one container. You should not do all in one containers. It's an anti-pattern. That's the reason why I call it bad. It works, but it is bad. The right way to do it is like this. Another application. You should have a separate database and a separate data store, but I am cheating just to make room and not have this exercise fail on you. We have another container called Redmine. This container connects to a database. Let's go identify what is going on item by item, beginning with this one. 5, 4, 3, 2, port number exposed right there. Postgres. That's the container, this one. Next container, Redmine. This one exposes itself as C4. I should not have this person yet because I need to have a proxy first. Then the person, the visitor, the user. Drawing it further, identifying further elements. This Redmine thing is also running somewhere here. There it is. It is exposing port number 3000. This is just the name it goes by. Call me C4. I am Redmine, you can call me C4. That's the way it is describing itself to the proxy. I am Joomla, you can call me C3. That Joomla is running here on port number 80. Then we have this guy. You can call me C2, but I am WordPress. And that is this guy. It is also exposing on port number 80 in the container. Next one is the C1 guy. The C1 is the Tutum WP, not the regular WP. This is the regular WP. This is the Tutum WP, the bad one. The anti-pattern one. This also exposes itself on port number 80. Here is port number 80. By the way, it also exposes port number 3306, which is the idea, tells you that this is the bad way of doing things. They are inserting MySQL right in the same container. MySQL also in there. Boo. 3306 also exposed in the same container. This application connects to the same database in the same container. That's a bad way of doing things. I just want you to understand it. That's not what you should do. Keep ideas separate here. Then this one. This is a container running MySQL, that MySQL. It exposes port number 3306. This 3306 is exposed in the container level. This container can access this database on port number 3306. This container can also access the same database on port number 3306. The red mine can access this PG database on port number 5432. This guy exposes itself on port 80. This guy exposes on port 80, 80, and 3000. This guy says, call me C1. You can call me C2. You can call me C3. You can call me C4. When a visitor says, okay, give me C1, the proxy says, by the way, the proxy is also here. Write that one. Proxy is exposed on the machine port 80 to the container port 80. It is doing the proxy port mapping. This proxy is actually managing the traffic appropriately to the request coming, C2, C3, whatever you ask for. It will know where to send the traffic to. That should finish out everything. We have one more data storage that stores the data, and that is this container. Are we missing any container? One, two, three, no. We covered all these containers. Now, having seen this picture illustration, what I would like to do now is to actually take a snapshot because I want to erase it, but I want to get back to it. I want to take a snapshot and pass it along to you. Here is a snapshot coming. I think I took it. Here is the snapshot. I'm going to save it, say, export it to preview. There we have it. Preview has it. I'll move it to the side. Now, it is the ink annotations and move forward. What I want to do now is just play around with the setup that we have these containers running. I should just visit localhost. What do you think I have? I'll say localhost. What do you think I'll get? Any comments? I'll say localhost, show me what you got. What do you think proxy will do? It will give you an error because it doesn't know what to do with the localhost request because it doesn't know where to go. It knows C1, C2, C3, C4, but it doesn't know what localhost is and what do you mean by localhost. You will get a 503 error and there it is. Now, we will go to C1. What do you think you will see there? Here's the picture for your reference. C1, what do you think you will see? If somebody asks for, this guy says, give me C1. This is your C1. That's what you will see. What is this? This is some kind of WordPress, some kind of bad kind of WordPress. Bad meaning it has MySQL database also in the same container. That's why it is bad. There's no other badness, but that's the only badness. Let's go to C1. You should type HTTP colon C1, by the way, not just C1. HTTP colon slash slash C1 and then another slash. That should open up WordPress. Here it is. This is your C1. I'll just fill it up quickly. This is probably an old version of WordPress because Tutum is not updating it. Tutum died. It got acquired and Docker Cloud also died and Kubernetes 1 and all that happened. This is your older version of WordPress. You can see it. It is functional. It is C1. It is working and all that good stuff. Let's open another tab. Let's go to C2, HTTP. C2. What do you think you will see here? Well, this is another WordPress. This is the right way to do WordPress, the three-part way, the three-tier WordPress. We'll call it C2 and fill it up and log in. This is your C2 WordPress, number two. Now, we'll go to C3. What do you think you will see there? Your image again. The image will tell you what you will see. If somebody asks for C3, the proxy will send them to C3 and C3 is running Joomla application, which connects to the same database, but that's a different story. The application itself is going to be showing us Joomla. That's what you will see when you go to C3. Let's go see Joomla now. We'll open up HTTP and here you see Joomla. Next, view tab, HTTP colon C4. Enter and you will see red mine. That's the demo for this multi-part, multi-container proxy behind a proxy, all the port mapping, all the things that we discussed about what we did. There are more examples, by the way. That's what I will do next. It is very similar to the previous example we just ran, except let me just quickly review what I have here. C3, C4, C5, C6. We'll have some fun now. What we'll do is instead of C1, C2, we can actually do a pretend game. Pretend that this is New York Times and CNN.com and something like that, some crazy pretension. That's what I will be tweaking this exercise to make it slightly more interesting to give you real-world perspective because the C1, C2 doesn't make too much sense. I will change the C1 in two places. This is your C1 in one place, this is another C1. I'll call the C1 container CNN.com just for the sake of having some fun with it. Next, C2 container, I will call this New York Times. Not My Times, but NY Times, like that. The C3 container, I'll label it as the Joomla one. I'll label it as FoxNews.com. And the Redmine container as Cloud Genius site. Let's see what happens. The names I am exposing to make it more realistic, setting virtual host references to point to these names that are not in my control. One of them is, but I don't control FoxNews, I don't control CNN, I don't control other sites that I've used, NY Times. I don't control those sites, but I do control my computer. I just want you to know that I do control my computer, which is obvious. But let's bring the whole stack down. So like Docker, Compose, down. So it will bring the whole thing down and then I'll bring it up again. But this time I will make a tweak. You can probably guess what I'm going to do. If you can guess, please tell me. And so if you cannot guess, I'll assume that you don't know what I'm going to do and do it. If you tell me that you already understand what I'm doing, if you tell me that, then I'll skip and do the next part. But I think I'm not hearing anything from you, which means you don't know what I'm going to do. But it's a DNS change I'm doing again. So sudo vi at chost, you can now guess what I am going to make happen in this illustration by going and making an entry here, cnn.com, newyorktimes.com. What else do I have? Foxnews.com and vacloudgenie.us. And now having seen these entries in my host file, hchost file, I'll save it. What do you think will now happen when I say docker compose up and it will bring up the stack? All that is good. But what does this mean? What did I just do and why did I do it? Well, it means that if you go to C4 now, you will get nothing. And C2, you will get nothing. That's one meaning. C1, nothing. Localhost, nothing. C3 is also nothing. And so we have all these nothings now. But what does that do to us? Like why did I make the change that I did? And what's the point? So let's go focus on that. What I want to do now is to actually visit cnn.com. What do you think will pop up here? Any ideas? If I say cnn.com in this browser, only in this browser, and I want you to pay attention to this docker image, sorry, this docker compose yaml file with this virtual host reference and the browser window where I'm saying cnn.com. So what do you think will happen when I enter? What will I see? It'll work. It'll show me what? It'll show you cnn.com. No. Okay, fine. It'll show you WordPress. Let's see. It'll show you WordPress. Here it goes. It'll show you whatever it thinks it has. And so it is telling that I am WordPress. You call me cnn.com. You can call me cnn.com. That's what it told the proxy. So the equal is literal as opposed to like an equal equal which assigns? This is a parameter assignment. This is actually a reference to a parameter that says virtual host is this. So now if you go to the next idea, which is this tab. In that tab, if I say New York Times, nytimes.com, and then hit enter, what do you think will happen? Well, you see the WordPress. Again, this time the other one. Which one? This one. The one that is the right way to set up WordPress. The correct way is to set up in three parts. Application and database separate, not all in one. This is like all in one. All in one is bad. This is good. That's what you're looking at here in my times. By the way, New York Times is actually a WordPress site. Next, scrolling ahead, C3. I'm now going to go to Fox News in this window and say C3, enter. I see nothing. When I say C3, I get nothing. When I say Fox News, I will see Joomla. And next is this one, C4. When I hit enter C4, I get nothing. But when I say b.a.cloudgenie.us, and here you will see, and yes, you guessed it, what's going on? Do you know? This is a point that is very, very tricky to understand. If you do this business on a daily basis, you will know what's going on. It is a security principle in action right now. And it is basically preventing even me from accessing my own site because I have modified the DNS settings without doing it the proper way. So even though I control my computer, I have to clean up the cache in this browser in order for this experiment to correctly show red mine here. It did not show me red mine, but by the way, it did not even show me anything at all either. It should have shown me at least my site, but it didn't. It did not show me red mine either. That is because if you pay careful attention to this name and what I have typed here and what you actually see here is different. What I typed was this. And what you see there, HTTPS. And that is an automatic rule that I have set that anytime if somebody says HTTPS, automatically redirect it to HTTPS. So that rule kicked in. And then it tries to go to the HTTPS on port number 443, not port number 80 or 3000. And that's why it is unable to open, but then unable to go either here because of the redirection that happens by default on my domain with a technology called HSTS. And we'll quickly read that and then go back to clean the cache and you will see it working and showing you red mine after I clean the cache. So HSTS will quickly review also, but before that, references, clean out on the ink, privacy, come on, privacy and clear data and clear history and clear history like for everything, all of that. And then close this site, clear history one more time. Actually close these other windows also. And then clear history one, two, three, clear history, clear all, and all of it is gone and clear data one more time. Yes, it's all clean now. So now you close the browser and you open the browser and you carefully type with no S, just HTTP, and you should see the red mine thing popping up. So let's go to that. HTTP colon slash slash without the HTTPS flag. And now you see red mine. Now let us talk about HSTS. It's just a few sentences to understand what HSTS is. And that's a piece of technology that forces strict transport security. HTTP strict transport security, that is a technology I have implemented in my domain which forces any browser to switch over to HTTPS, even if the user tries HTTP. It is strictness that gets cached as a policy on a browser window. So when I clean the cache, it forgets. It doesn't know that cloud genus actually is the other site that you can actually access on this location, this site. It doesn't know, this browser doesn't know. All it knows is that this address goes to the proxy, which in turn sends it to this location. And so that location runs red mine. So I'm going to show you what I see, and that's what you see. And that's the idea behind HSTS. Having seen this, what I will do now is stop the recording and we'll resume the same set of exercises and then we'll add the security capabilities, HTTPS capabilities with automatic certificate generation and all that in a real cloud. We can run those exercises outside in a cloud setup, not on a machine like this. We'll do that HTTPS and related exercises next time when we get together. Before that, I want to remind you that we are getting together face-to-face in person tomorrow at that location. So let me just get you that detail. You have it already in your calendar system on 23rd, which is tomorrow. We are getting together at 1130 a.m. for Haiku Sushi and Seafood Buffet. It is in the Redmond town center area in Redmond. And I will be there at 1130 a.m. and I look forward to seeing you. If you can come, I would appreciate that. If you cannot come, that's okay. We'll get together again at another time. But if you are here right now and you are going to come, please tell me that you are coming. At least I know that you are coming. I know Rich is not. I'll be there. You are coming, Greg. Thank you. Dom, are you coming, I guess? I think you are coming. I heard I got a reply from you. You are coming. Vandana, are you coming? Sorry, I won't be coming. I'm not keeping well. First again, you will not or yes? I won't be coming again. I did not get yes or no? No. Okay, got it. We'll get together another time. We'll get together. Sure. And that's fine. So with that, I will stop the recording and I will resume. We'll see you tomorrow at 1130 and then we'll resume again on Monday, which is the next session day, which is 25. That's when we'll have our get to a video conference session again.