Docker Build: Containerizing a React.js Application

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
it's not working in prod indeed it's not working in prod well it's not my problem it works just fine on my machine and on the dev server well well i told you all systems are isos and if it's working in-depth it's working in practice it's iso oh yeah essentially i mean pretty much almost almost what do you mean almost you knew there's maybe a very small gap in minor versions and for some plugins nothing particularly important hello everybody thank you for joining yeah it looks like we have some folks on there watching already yeah i'm excited too all right well today i'm going to be talking about how to containerize your react application so um most we talk about node.js and containerizing middle tier applications but a lot of times we don't talk about how to containerize your front end application and it's actually pretty easy it's pretty straightforward so we're going to walk through starting from the very beginning uh creating our docker file and walking all all the way down to uh creating a image that you can use locally to develop and then also how to productionalize that so adding nginx to the front end as a web server um yeah so let's jump right in okay let me share my screen and go ahead if anybody has any questions uh while i'm going along feel free to put it in the chat there and i will get to them for sure let me just get things set up here how's everybody doing out there on this fine thursday morning afternoon evening depending on where you're at in the world all right you hear you heard my voice there okay sorry about that let's go ahead and share my screen let me move out of the way okay let's make that a little bit bigger bump that up nice and big there we go okay so i have basically a test little application little sample application that i wrote um that i use i use this kind of framework a lot for just showing some demos but it is a react application front end it's based off the create react app i like to use create react app because it's known pretty well out there in the live in the world so let's jump over here's the code base pretty pretty should be pretty familiar if you're a react developer so we have this index.js that kind of sets everything up we have one component called app that is right here um and it basically builds out skipping down to the render method sorry for the fast scrolling there um so you can see we're dumping out a bunch of html we have a little form at the top you can create new records that's here and then we show a list of records that we're creating at the bottom we have some loading and results so let me demo the app real quick um so i'm sitting right here i'm just going to do an npm start and let that fire up and i'll pull up my trusty brave browser and there we go so the application's running let's make that a tiny bit bigger not too worried if you can see the the demo app running it's not it's not that exciting to be honest with you but it does it does its job so let's let's create a new record um i'm going to call it name and we'll do foo my infamous foo let's save that oh got to give it a entity name at the top and these are all going to be foods so let's save you can see down here at the bottom we have a foo let's get a bar in there and we need a bath all right you can see i created a couple of records this is all just again just a test app nothing is being saved into a database i'm just saving it into memory for demonstration purposes okay so we have an app running just like you would normally we have uh create react app running a bit in the background we just have an npm start that sets up your um local dev server watch your file system and just keep uh restarting the application every time you make a change actually let's just show that real quick let me restart it here back into the app refresh over the code base let's find um let's find the submit button right here you can see right here that's the submit button that's this button and let's make it say go save that oh there we go just as normal you run and create a create react app application um it has a little dev server it's watching our code it's refreshing you do this all the time if we needed to go in and and uh set a break point so let's handle this submit i'll just put a break point right here come back click on go and there we go you can see i'm able to debug everything's normal working the way you usually would so let's take off our break point okay so let's talk about let's change this back let's talk about how you uh dockerize an application so the first thing we want to do is we need to create a docker file so i'm going to do this just as a side note uh you can see i'm using vs code vs code has a lot of plug-ins there's a docker plug-in you can actually use the plug-in to create a docker file for you a compose file all those type of things but as we're learning i would like to do it manually so everybody can see the steps i go through and my thought process behind that so first thing we want to do is let's shut this down i'm going to touch i'm going to do it whoops do a docker file so i'm going to create a docker file now we have our docker file okay so normally when you start working on a team or you're working on a project um you would pull the code down from let's say github from a get repository let me take a look at see if we have any questions or anything um sorry my screen is a little bit small here okay yeah so raphael asks tell us a little bit about uh let me hit that button tell us a little bit about docker before we get started just in general so i can bring everybody up to speed great great question sometimes i assume that folks know what docker is and um don't talk about it so yeah so what docker is is a way that you can containerize your applications and then run those applications anywhere that you have a container runtime a docker engine kubernetes eks aci which is azure container instances ecs um elastic container services anywhere that can run uh a container a standardized container you'll be able to run your application so what a docker what a what a container is is a running instance of a image and what an image is an image is a collection of all your source code compiled code not necessarily source codes forgive me think it in the javascript world where it's not compiled so if you're in a compiled language like c it would be your executable file all your configuration files all support libraries operating system support libraries anything you need to run that application you can put inside of an image and then once you have an image you can run that image inside of a container and what a container is is it takes your process a normal operating system process so a normal linux process the same as if you would run a process in your terminal takes that process and it isolates it from the rest of the system so it restricts access to the different files to networking you can even restrict to how much cpu usage how much memory usage uh network access all those type of things but at the base of it a container is nothing more than a normal operating synth system process but it has been isolated from the rest of the system an image is where a lot of the power happens these two things combine together but in images everything zipped up basically in a tar file so all those files configurations exes everything you need to run your application is put into an image a package then it has some metadata on it so then when you go to run that image inside of a container it knows how to run it and the different things like that how it should be configured and so it packages all that up in an image and then you can share that image around so you can push it up into docker hub you can pull it down from docker hub you can run it in aws in azure gcp in your internal own cloud you can share that with fellow developers as long as you have the docker engine running you can run that image okay hopefully that was clear enough if you have any questions go ahead ask me in in the chat and i'll try and get to them all right awesome so to be able to create a container which is an image running inside of an isolated it's a process running isolated on the system you have to create an image so to create an image you start with a docker file and basically a docker file is a list of commands that you would normally run to install your application to get all this configuration there and to actually execute it so let's take the scenario that i have a server running somewhere maybe it's an ec2 instance maybe it's just a vm in my uh internal uh cloud at my um at my company and i need to run my application there so before containers you used to ssh into that server make sure the op you know you would get the operating system installed you would set up the vm and set up the vm get the operating system installed then you had ssh into that vm and you would install let's say node the go run time the java run time the net runtime then you would get your application code in there all of its configuration and then you would run your application right and you can automate that through scripts but that doesn't scale very well right you have to point it to each server make sure you run the exact same script with all the setup you could even script how you run that script on different servers but it comes complicated and there's different ways that you can different tools out there that can handle that but at the base of it it's a lot of manual updating and you also have to worry about the server all of its security patches all those type of things but now that we use containers and by the way container technology has been around for a long time docker didn't invent container technology what docker did made it what docker did was made it very very simple to use those operating system constructs that allow you to containerize an application containerize a process so um like all great technologies i know have said this on the show before they level up the abstraction so it allows you to work at a higher level of abstraction that's a lot easier for you to reason about right if every time we had to create an isolated process on a system on a server in the cloud we had to be see developers and go write c code and spawn processes and give it the correct permissions and restrictions um that's a pain right that's hard to do it's not scalable so docker came along and took all of wrapped uh the docker engine around all that and allows you to do that with a simple couple simple commands okay so let me take that question off of there okay so jumping back a little bit to be able to create an image we need to create a docker file which again is a list of commands that produce an image and those commands are going to be very very similar to what you would do if you scripted out let's say a bash script that you would run on a server to install your application and so the first thing we want to do is you typically don't start out with a base with this with a blank image right we have what's called base images so docker images you can kind of stack on top of each other you can kind of think of it in object oriented [Music] terminology right so we're going to use inheritance we're going to use a base image and we're going to inherit from it and we're going to create our image on top of that right so it would be the same thing if i had um let's say a person class and then i wanted a user class that had so the person ha class had first name last name phone number and a user then has a username and password but it also has a first name and last name so we want to use the zap function out of that base class and so we extend it and we add some more functionality onto it so that's what we're going to do with the base image so we're going to take a base image and we're going to use the node base image for now let me get the exact version i want to do well let me walk you through the process how i think about grabbing a base image so so the command you use is called from so from will pull down from docker hub that image put it into your image and then build on top of it um so i'm going to use the node 14.17 and where do i get this number from what what is this here so this is the fully a full reference to an image name and where our images live they live on um on docker hub so let's go in there so i'm going to go to hub.docker.com and come to the search box i can type in uh not hub i can type in node our search engine goes out we see that we have a node image here now how do i know this is a good image that i should use well we can see over to the left here that it's an official image and what official images is that goes through the process that we have here at docker to vet an image that is done with best practices in mind uh that it's secure and it's something that you should feel very confident about using right now in the news there's a lot of talk about um uh software supply chain attacks right and um we're gonna be talking about that coming here real soon in next couple weeks but the idea is you you should really know where you're getting your software from right the internet is the wild wild west still is right and so pulling random software off the internet and just running on your computer is no bueno right you would not do that um you know my parents do that right download software off the internet and run it oh yeah hey let me try this let me run it don't do that we shouldn't do that as engineers either so go to a good reputable place such as docker hub use the official images the verify publishers program so those are uh isvs that we verify that they are publishing those images onto hub and they are who they say they are so ibm red hat nginx those type of things these are the verified publishers or official images right so you can see docker uh so node here is it's a docker official image and i'm not going to go through all this but let me scroll down a little bit so after we pass the topic i'm going to come back and talk about that but it tells you what this image is it tells you how to use it it talks about the variance here not all readmes on all images do the same thing but the known images does pretty well of explaining to you what each one of these tags are and what they mean so i'll leave it up to the viewer to go and check this out you can read through it but basically you have node which is the name of the image and then you have a tagging system right and you can see here that node is talking about we usually put that they usually put the version and then you have a dash and then some kind of a name right these names are referring to usually the base operating system that that image is built on top of so as we scroll back up and look at a list of images uh tags also too you can come over to the tags here and go down through and see what tags there are and you can dive a little bit deeper into the details but staying on the description so how do i know what tag to use right well if you already know what the lts the long term uh supported version of node is you can find that um right see if there's an image built for that right here or what i use what i typically do a lot of times is i come over to nodejs.org and you can see it right here so 14.17.3 lts long-term support uh there is a 16.5.0 current right you could use this image also i like to use the lts as i'm doing demos just because it's uh supported it's it's and it's pretty reliable so we're going to use 14.17.3 so let's come back over to node i'm going to do a little search so 14 got 17.3 that's big enough apologies if it isn't let me scroll up okay so here we can see we have 14.17.3 dash alpine alpine 3.11. so this dash alpine is telling you that we're running node 14173 on the alpine distribution which is a very slim slim uh distribution of the linux os um here's a 3.1 version of the alpine free uh 3.11 sorry 3.12 1314 and here's buster so buster is the code name for an ubuntu distribution of linux or linux we also have buster slim which is an ubu slim down version of that os right um but we're going to stay safe we're going to use the umbutu version of 14.17.3 so 14.17.3 dash buster so that's what i'm going to use when we build as our base image so i have 14.17.3 let's go to buster and this is very nice let me show this real quick so vs code will give you some uh type of heads right so i can see it right here okay so again just to review real quick so the the from command now the front command allows us to do a little bit of object-oriented programming style it's not exact for sure but it's a good analogy so we're going to take a base image called node 14.17.3 buster and then we're going to build our image on top of that we're going to put our source code in there we're going to build it and do all those things right but instead of us having to add all the support actually install node into the image get it configured correctly we have a base image that's already done that so let's just use that and then let's put the bits into our image that we need right uh separation of concerns basically okay yeah raphael alpine four slash no it's a good one too right there's a there's a bunch of really good images we could probably do spend a whole hour on um unpacking a little bit more on how to think about your base images and it but really what it comes down is it depends on what your need is for that image right okay so the next thing we want to do is we're going to set up a working directory so a working directory this working directory command basically tells the docker engine every other command that follows after this um create a directory called forward slash code and and this name here is arbitrary so this could be uh web this could be uh source you know it could be anything you want it could be uh foo i like to call it code uh some people call it workspace some people call it web app you know whatever you feel most comfortable with use the name you do i would say try and keep it consistent across if you're in a microservices world right try and keep it consistent so that everybody knows your source code your working directory inside that image is going to be named the same so if you get an image that's running and you have to you exact into that image you know where to look um okay so the working directory will create a directory called code in this case and then we'll move us into that working directory and all files below that will be relative to the working directory not all files all command i'll command you run subsequently after the working directory will operate within that working directory okay this is the same thing if you were working locally um you would see you would create a uh probably create a folder or directory in your projects folder right where you keep all your source code you would cd into it and then you would pull the code down right with a github clone something like that right and so that's kind of what we're going to do here we need to get our code inside of our image so the first thing we need to do is we're going to copy in our package.json files and our lock file and the reason i'm copying these in individually is um because of caching and the way the docker engine works and i'm going to come back to that after we build this and we'll talk about caching in a certain order that i put these commands in um i don't want to muddy the waters right now so just think of it as you seeding cd into a working directory you clone the application and now you have your files there we're going we're doing a very similar thing a little bit out of order but the exact same idea right so now we copied our package json into our working directory code package.json and actually we could take this off as we set our working directory up here so copy package.json from my local machine into the image in the working directory of code and call it package.json and then the same thing here we're going to copy in our our lock file okay and now we want to install our npm packages so we're going to use the command and we're going to um npm if i could type npm install just like you would normally on a command line right i do npm install there we go it's going to go out it's going to pull down all the packages it's going to install them update them all those good things right okay so that's what we did there next thing we need to get into our oh and the command does exactly that it runs a command oh this should be run we're going to use the run command the command we're going to use a little bit later it's different so the run docker engine command is will execute a process inside of your image and the result will stay inside of your image so we're going to run npm install inside the image it's going to look at the package json inside of our image in the package lock and it's going to use those and install all of our node modules inside of our image exactly how you would do if you're working locally get clone npm install is usually what you do first right if you're using node or frontend app like react view angular okay so now we have all of our node packages installed let's get our source code into the image right so we're going to do another copy command and i'm going to take everything in my local directory and copy it in the working directory okay so i'm going to take all my files that i have over here and i'm going to copy them into my image okay and then what do you normally do after that so you get clone you grab everything you run npm install you don't need to copy anything locally because that's what the the get clone did you're going gonna you're gonna start your application you're gonna do an npm uh start so we're gonna use a command called command cmd what the command is this doesn't get executed as you're building the image this tells the docker engine what command i want to run when you run this image inside of a container right and we're going to use the the the json structure here i won't go into it while i use this uh it's just cleaner um you can read in our documentation why best practices around using uh the json array um format so docker run start i'm gonna be explicit and call docker run uh npm run pardon me uh just so npm knows it doesn't get confused okay so let's say that right now that's our docker file should be very uh should be very simple everybody should kind of understand what's going on here let's just review real quick before i actually build our image let me save um so you're going to start off with a base image we're using node 14.17.3-buster we took a look at hub and we grabbed the official image the first part of this tag is the version of node that's the lps i got the lts from nodejs.org website and then the dashbuster telling us that this image is built on top of ubutu buster buster is a code name of a release of a bluetooth okay then i set up my working directory i basically do a make directory code and then a cd into code all right and then i'm going to copy pack package json from my local machine into the image and then i'm going to do the same for my package dashlock.json file and then i'll run npm install get all my packages installed i make sure my source code is inside of my image and then i'm gonna say hey docker when you when you start this image this is the command i want you to run npm run start okay if you have any questions drop them in the chat but let's go ahead and give this a shot so the next thing we need to do is let's clear our screen we need to build this image so the way you build an image is you do a docker build i'm going to give it a dash t which tells it to tag the image give the image a name and we're not going to we're not going to call it prod but we're going to call it dev so react docker colon and then i'm going to give it a tag of 1.0.0-dev i'm following that node.js kind of tagging system and then after you do that then you need to tell it what's your context so for the docker build command you give it a context and that that tells docker when you do when you tell it to run commands such as this take everything in my current directory and move it into the image inside of this you're telling docker with the context you tell it this is where i'm working you should execute this docker file within this context within this uh folder so to speak right and you can change the context so i can have this docker file in one folder and when i do my uh my docker build i could say something like that and say uh source right and it will it'll go up one directory it'll look in source and use that as a context right your ex your docker file might be in a different location um but that's what this dot is doing so again i'm doing a docker build command i'm doing a dash t for tag the image name the image and i'm naming it react docker colon 1.0.0 dev okay so let me hit enter it's going to go ahead and build the image and it's basically running those steps that i have in that docker file you can see right here so one of six from docker so it's using the buster image two of six it's gonna create the working directory it's gonna copy my uh my package.json files in my log file in it ran npm install copied all the files in it's saying let me export what i just did into an image and to do that it exports layers writes the image here and then it names it right so now we can do uh docker images and take a look so here's the image we just built 25 seconds ago right let's now the next thing you want to do is we're going to run the file and we're going to make we're going to we're going to run that image inside of a container and make sure everything worked make sure our application's still ready so to do that we're going to do a docker run we're going to give it a dash you can see i've typed here already so def so let me go through the commands the switches here so docker run dash dash rm means remove so when you automatically remove it when you stop this container so when we do either control c or we do a docker stop when that container is stopped if it if you started it with the dash dash rm it will also remove it so the couple status is when you run a container it could be started it could be stopped you can restart a container those type of things so when you stop it it doesn't go away it basically pauses that process and you can restart that process you have to remove it to actually remove that process unless you started with the dash dash rm okay then we give it a dash it which is an interactive terminal um and then we do name so i name my container do a dash p which publishes a port so um this is actually going to be three thousand so if you're familiar with create react app it default runs on port 3000 i didn't change that anywhere we could probably jump into the source real quick um i don't think it's oh forgive me that's the this is the uh react app um sets up a dev server and that default port is on 3000. uh later on you're going to see when i add in androidx how we set the port so the default dev server for create react app runs on port 3000 so we're going to expose or publish port 3000 on our local machine 3000 and we're going to map that into port 3000 inside of the container if you remember earlier when i was talking about images and containers so we're gonna we have this image that has all of our files in it that's what we did with our build and then when we run it it's gonna run inside of a container but that process is isolated and it's isolated from the network by default so we basically have to give it a firewall rule we're going to say publish port 3000 in and direct traffic from on local machine port 3000 into my container on port 3000 so that's what i'm doing here with the dash p and then i gave it the name of the image that i want to run so react dash docker colon 1.0.0.0 dash of dev and that name should be very familiar that's the name that we gave our image in the previous step okay so let me hit enter let's run our image you can see it's very similar we've seen that before when i was just running on the command line we started with compiled cloud successful running on localhost 3000 so let's take a look here um so that is port 3000 we're still running running nice and fast there okay let's make sure the app still works let's give it a name let's create a record aim foo let's save that cancel that out so we can see it okay it's working things are great let's clear this out go submit we should get yep okay functioning great we can see right here that things have been looked totally normal as a create racked app just the same thing as we did in my terminal but everything now is inside of that image that we created so you can see right here on my terminal let me go into another terminal and let me bump that up nice and big for everybody it looks about the same let me do that okay cool so now we can do a docker ps and what docker ps is basically tell me what's running what containers are running on my system and you can see i have a container id the image name is that image we looked at here's the command that was run uh here's the entry point i'm not going to talk about entry points right now but you basically have entry points and then commands an entry point is um usually uh the default place where default command that will get executed for uh your image when it's run inside of a container and then it tells us created a minute ago status is up and running and then it tells us what ports are being mapped so you can see 3000 on local is being mapped inside of my container and then it tells you the name web okay so we have the image running we can x execute a command inside that container and we're going to execute we're going to give it a i t we're going to tell it what container we want to execute and then we're going to i think we have bash let's give it a command whoops you gotta spell docker right i can't type there we go okay so now we're inside of that container we what happened here is it created another process inside of that container that's able to see everything that's running in that in that container that's isolated inside of there so you can see it directly put me into forward slash code so if we do an ls lists our directory ls.l a little bit easier to see you can see i have a docker file in there i have a readme i have no modules package public source okay excellent so let's x exit out of there and we're clear come back now normally what what did we do last time we fired it up normal on our terminal then we went and made a change we saw the change happen so let's do that let's test that out so we come up back over to my application that might be a little big there we go okay let's find there's the submit button again let's change it again to go before i'll save let's just come over still says submit still says submit okay i have go you can see that it needs to be saved i'm gonna save it now it's saved let's come back oh it's not updating what's going on well what's happening i set you up of course so what's happening is when we were running locally all of our files were local we ran that npm start it did some magic where it uh battlefied your code and then it puts a little dev server and serves it up it watches your files anytime you change it updates right well now we have everything isolated and running inside of a container we're able to see it because we expose port 3000 that's how i'm able to see it but this file i just edited is not inside of that container that running painter it's outside of it right so we got to figure out a way is how do we edit the files inside of my container so i can develop inside of that container one of the ways you do that one of the easiest ways you do that let's come back over here let's start let's stop our uh container from running we'll jump back over here we'll do a docker ps i can't spell docker today okay and we see that remember we did docker psb4 we could see our container running since we hit ctrl c on the command line here that stopped the container again if you remember i did a dash dash rm so when it stopped it removed it so we don't have a container just paused out there all right so now we got to figure out a way how do we edit the files inside of our container so we can make changes and we can see them updated on the screen so let's do that one of the best ways to do that is to use bind mounts so i'm going to do a docker run and this is the command we just run before but this time i'm going to give it another flag a dash v for volume i'm going to give it my working directory so pwd so if you do a pwd here that gives you the print working directories i believe that's what that stands for pwd um return working directory name okay i use p as print work and do it anyways um so that's what that's gonna do it's gonna print out so we are currently in docker examples acme right so that's what when we run a pwd let's just do that now so if i run a pwd you can see it gives me the fully full name directory name of where i'm at for path to the directory name so user peter docker examples acme so this that is what this will equate to when we run that command where do my docker run go so docker run so let's give it a dash v pwd pull in so we're going to say take this local directory on my local machine and map that inside of the container so i'm going to map it into code because that's our working directory that's where our source code is at it's going to map that into that image the same the docker run command is exactly the same now we added the bind mount uh flag so let's enter so we're gonna start up again again looks very similar it's just as we ran it locally uh just reading some commands here [Music] yes the recording will be available this should it'll stay on youtube it'll live in perpetuity um let's put it that way and um yep so it'll be available later uh naveem uh let me know you might have asked this so i i might have answered this if i didn't answer this i let me know again i could go back over what command is and why don't i just go back over it again really quick so the cmd so we take a look at our docker file so if you remember here when we run when i did the run command that runs whatever command comes after it when we're building the image okay the command command will get executed when you run your command not at build time so now when we did a docker build that's when line 8 will get run when we do a docker build when we do a docker run is when the command will get run so the command command i gotta think of a better way to explain that but the command tells the engine hey don't run this when you build but when you run my image inside of a container the process that i want you to start use this command to start that process so the command tells the docker engine what process to start and how to start it let me know if that doesn't make sense um do we need to expose port 80 in dockerfile or it takes takes by default i always expose it when i run it you can you could put a an expose here like it type so expose 80. um you could do it in here i i explicitly uh expose them when i run the command command line okay please explain dash dash rm again yeah so let's let's jump over here let me go here clear so docker run and let me do that help and let's let me move my microphone out of the way sorry for the fast scrolling i'm trying to find the rm should be uh alphabetical there it is so rm so automatically removes the container when it exits so um let's see let's do this so let's do uh docker run um ip in the background don't worry about that for right now i think we go busy box they're real so that's gonna pull down busy box and it's gonna run it so let's do a docker ps okay so you can see we have busy box running and you see the status here it's up two seconds ago so let's stop busy box it's optimistic cnoc let me grab that name you can actually use the container id so let me do that so i'm going to do a docker stop should stop the busy box oh come on don't mess up my example here there we go okay so now let me do a docker ps again you can see it's not in the list but now if i do a docker let me take this off the screen um it's gonna make clear so it's easier to see so now we do docker ps it's not there do a docker ps dash a that says give me everything show me everything that was running um let me grab this name okay so you can see it exited right uh 17 seconds ago so let's try and run it again so we do uh docker run busy box i'm going to give it a name the same name if i can type same name as before and it says look there's an error uh error response from the demon that's the docker engine saying hey you have a conflict you already have a container running that's named that but you might say this happens a lot people ask me this all the time you do a doctor ps and you're like well i don't see it running what are you talking about right that's where you need to do um so you all can see that's where you need to do a docker ps dash a that shows you everything and say oh there there it is right so we stopped it already remember i did a docker stop but now i'm going to do a docker remove and give it a name no so now if i do a docker ps dash a you can see it's gone if i do a docker ps now if we try and start that docker um that busy box image enter again see um with that same name that we've been using and there it goes it'll start back up or not start back up it'll start the image again a new image inside a new container sorry image and container uh you know sometimes they're interchangeable but it's they're not the same right so it's starting a new container um you can see it running so we'll do the same thing what i do a lot of times is i do just um uh rm-f and then let's grab the name copy it so a little shark up instead of stopping an image then removing it you can do an rm if you don't push the that uh put the dash f flag which means uh force it's going to tell you hey i can't remove it it's still running the dash f will stop it first then remove it so we'll do that and now if we do a docker ps a it should be gone okay hopefully it answered uh the our uh rm uh question yes we are herbert we we're gonna do uh multi-stage here in a second okay so we built our image um where were we do we do we update that code yet let's take a look sort of change there uh nothing nothing like doing live demos let's see we're at okay well i got my code changed um it's saved well that's right i stopped my image and i mapped in the volume let's do it again just so i could show everybody so if you remember when i first ran ran this not busy box oh my goodness can't type zbox so there we go okay so the first time i did it i didn't map in a volume right i didn't bound mine a bound amount of volume into the container so when we change the file the server updated it said oh yeah there you go it's still running but it didn't see a file change because the file we changed lives outside of that container right so now what we're going to do is map that in pwd for the print working directory and then we're going to map it into code enter start back up wait for it come on react dev server there we go and we're going to see some magic happen here not real magic but if a second is still spinning up there we go and you can see it's been changed what happened there right we didn't copy anything in but we did the bind mount and mount my local files into that image and it picks up the change so now we're running we're live we're still running let me go back to the source code let's change this back right let me save it we come back to and there we go it's been saved it's been updated pardon me so one two say let's see if i can i'll tab quick enough there goes now i got one two right so now we're running inside of a container our application is running inside of a container it's watching our files our files local files have been source code has been mapped inside of that container we're changing files outside of it but they're being synced up inside the container and we can see our changes right inside the container you can even you can even debug so when you hit this one two button you can see it says please enter uh edit any name let's see if we can find that source code so i'm just in uh um you know the debugger the the browser debugger the chrome tools so open up source i'm going to go into app.js i know this is the handle submit of this one-two button so i'm going to put a breakpoint right here come back in click it fantastic so we are now running our application in a dev mode inside of a container and we're debugging right in our dev tools in the browser and we're able to change source code right in our nfvs code right in in reality theory and reality you could had a brand new machine with get installed uh and um docker and vs code the only thing three things you need you don't even need vs code there's no magic we're not using vs code we can use a text editor you can use a vi emacs that come with your machine so you basically we basically installed git um which probably comes with your machine nowadays so we got git and install docker engine we cloned the repo right we run the docker file we run the docker file build our image we run that image inside of a container we map our local source code into that container and we're often running and developing that means you can have that docker file let's say you have a couple different front ends that are running a couple different versions of your tools right and you don't have to install it all locally it's all inside of that container okay you can debug do everything let's stop the debugger let's keep going all right so that's pretty cool let me jump up the questions herbert's waiting we're getting there brother we're getting there okay so awesome so the next thing i wanted to talk about real quickly is um how you run um yeah so the way so the way we did this right so if we let's take it back let's take a look at our docker file right so this is all fine and dandy but we don't want to run a couple things wrong here though we don't want to run mpm when we're running our container in production right we just want to run actually with the react and view and angular and raw html and javascript nothing's getting processed on the server nothing's getting executed as opposed to like node.js that javascript is getting executed on the server right but with react and all of our front-end tools the front-end so they get executed in the browser right so all we need is a wicked fast web server to get those files from a server and get them down to the client as fast as possible right and we don't want to run npm we don't need it right we do need to babblify our our javascript right our react application and get it all minified and and all packaged up nice and neat put it all into one file and serve up that one file okay so let's take a look at doing that and this is where we're going to start talking about multi-stage builds um let me pull up my sample so i have to remember my whole docker file from from um scratch okay so what multi okay so two things we need to do right we need to run mpm to get all of our node uh no modules and put into that image and then we got to run that build process right to take everything and package it all up okay so that's one step that's our build step with a react application right so we're going to create a build step in a multi-stage so we're going to create a build stage so i'm going to call this build the way you create different stages in your multi-stage docker file is you label them at the from command so i'm saying take from the node we talked about that and label it as build right so now i'm kind of labeling all these commands as build all right i'm still going to set up my working directory i'm going to copy my package json files because i'm going to need those to install no packages but i'm not going to do an npm install i'm going to do an npmci production there's different ways you can do this i won't go into all a bunch of best practices but you might remove cash you might remove different things right there's some streamlined ways you can run this but mpmci productions is pretty darn good okay so we're going to do that we're going to load uh install of our npm packages for production right we're going to copy our local source files into the image but instead of running instead of telling it what command to start inside that image we're just going to get rid of this uh no we're not we're going to run uh excuse me we're going to change this to a run command and we're going to do mpm run build all right and i assume most of you on here probably watching are least no npm or react folks but let me just show what it's doing so if you go into package.json you have a script section these should be very familiar if you're doing a create react app if not you probably have modified these somehow your application's done uh your development team has added scripts in here or not the way they do uh the way your team runs things but they're gonna be very very similar so we have a uh react scripts build and basically what react scripts build does is goes out uh looks at all your source file uh minifies it packages it all up into one file puts it into a build directory takes all your css and puts it in one file creates an html that references those two files right and now we'll have an index a javascript and css file and then we can use those and just serve those up from a web server okay so we're running npm ci production make production uh builds and then we're gonna run npm build take all those files put them all together and do all the things i just said awesome if we just built this image now it would run it'd be great and we would just have an image and we'd run that image inside of a container and it would do nothing right because we didn't give it a command uh actually what it would do is drop you into uh the node um rebel that's the default uh process that gets run when you don't tell it what to run and that that comes from uh the base image okay so that's our stage that's our build stage that takes all our code files source files packages and them all up builds them packages them all up and they're ready to go okay so now we're going to add a second stage in there it's going to be our nginx server so i'm going to copy this in just enough to type it all out for folks here so same thing we create another stage we call it uh as prod so we're going to call it prod right and we're using nginx uh version 1.12 dash alpine so the dash alpine is the alpine uh distribution that nginx has put on top of alpine's very slim small distribution linux distribution okay and then we do these commands should be very familiar now we do a command a copy here's a new flag though we're going to do a dash dash from so what the dash dash from tells the copy command don't look locally but look at this other stage here build and as you can see it's labeled up here and builds so it'll go look in this temporary image for the files for the copy so it's going to say copy from build up here in code build take all of those files and put them into this new image that i'm creating and put them in user share nginx html if you used nginx before this is the default location for where nginx serves serves up file static files okay so we do a second phase we say i'm going to create this image based on nginx i'm going to copy the files from the earlier stage where i built everything copy those into this image and then just have nginx so we don't have node running in this nginx we don't have any other support files that might have been in the node right no text editors those type of things just nginx right and then we expose port 80 and then we tell it a command when you run this image inside of a container this command right here on line 21 that is the command that starts the process inside of your container so we're going to go nginx g i actually forget what it what the dash g is it's going to tell it demon off right and so it's going to run up all the it's going to use the default configuration that's set up in the nginx server it's going to look into user share nginx html for the files it needs to serve and it's going to serve those up so let's save that wow well thank you thank you herbert said the real time debugging inside a container it's magnificent thank you very much awesome okay so here's a good question let me pull it up do you need to copy source code into the image since you mapped the source directory to code oh earlier when we when we yeah so let me um let me copy this real quick and then let me undo everything back the way we had it oh you know i don't know yeah so sorry sorry sorry sorry let me delete that out of here we had a different way a command here but you're talking about this um this command right here in our dockerfile the copy right so um what richard is asking hey is that that second time you ran it you mapped your you mapped the volume inside of the container which had your source codes locally and now it's inside the container did you have to actually manually copy everything in in the docker in the darker file when you originally built the image you don't it depends it depends on how you want to do it right i like to still copy it in because if someone else is using this and they don't map their mount their volume into the container then they won't have any source code and nothing will work everything will be broke and then they're gonna they're gonna slack you and say hey your image doesn't work you're horrible we should fire you um no i don't think they'll fire yet right so yes technically richard you don't we wouldn't have to we could we could have commented this out and we could build the image and then we uh map in our source code and it would be there and everything would have worked fine yes i'd like to copy it in in case like i said before if you give if you take this image it's going to cop it's going to have a source code in in case you forget to bind mount great question okay let's see excellent there we go okay so there we go so now we have a two-stage aquifer first stage comes right here and it's labeled build and i'm doing all the things we did before we modified the mpm so we're going to do a production build and then we're going to run right away while we build this we're going to run an npm build so it's going to take all those files minified do all the magic that create react app does puts it into a build directory you have one index.html file right uh just for fun this is npm run build let's build let's let that build for a second okay so that was the first phase right second phase stage uh says okay create me an image use the engine x 1.12 dash alpine base image label it as prod copy the files from code build into user share nginx html but oh don't do it normally i gave you a flag dash from and i gave you the stage build so copy it from here that image we just did are nice productionalized files copy those from code build into my nginx container forget about everything else leave that all out there leave the package.json leave the source files all that stuff leave it out of there only cop copy the files that were built that now live in my build directory and now that i ran it locally you can see what gets copied in right so you get a manifest index.html nice and minified does some javascript magic here where it checks uh prototype has owner and all kinds of stuff right it does some magic to get your your code actually down to the browser so you have a manifest asset manifest um you can read you know you can go through here's the robots service workers uh react just um create react app sets up a service worker for you yeah not sure i like that but anyways okay and then you have in your static file here's our js here's all of our um did i hit the map i hit the source map so there's your javascript all nice and minified and um obfuscated i can never say that word correctly so it's obfuscated which basically means take take all the normal names i have in my variables and name them a b c t e n so it makes reading the code very difficult but you can still read it okay so you'll now you know what gets cop what's actually in the build the per the output of this ci dash i know forgive me this output of the mpm run build what actually gets outputted that's all these files and then you'll see a css i always hit the map for us so here's all the css that took through the application put it all together okay awesome sorry if i'm talking fast there but don't want to spend too much time on it takes all those files puts them into user share index.html exposes port 80 and then says hey nginx start up and serve these files awesome so let's cancel so let's save this let's build our image and then let's run it so come back to the terminal um so we have docker images right now you can see we have our react docker 1.0-dev right and so now and you'll see it's 1.25 gigabytes now i didn't have a docker ignore file we're gonna come back to that um if we don't run out of time but so now i'm gonna do a docker build again i'm gonna give it a dash t and i'm gonna call it react dash docker again colon1.0.0 let's just call it prod and i'm going to give it the local context again the context tells the docker engine where you want me to do the work where you want the engine to do the work right and so i give it a dash dot dash uh if your docker file is not in there in your context and if it's not named just docker file then you'll need to do a dash file and tell it where your docker file is to use okay so let's run this build okay going to do the same things before it's going to go down through the top it's going to start executing everything and there we go so we're on what 6 7 copying everything in it's running mp and build um so here it goes it's creating up an optimize let's get this off the screen so you all can see that let's do this maybe a little bit easier let me know if the if the font isn't that great i can bump it up [Music] all right thanks everybody it's only cool to us nerds i would say nerd trust geeks but um yeah it is cool thank you i appreciate it let me make that a little bit bigger so you can see okay awesome so we just built our image let's go to the top here i'm going to do a docker images if i can type again so there we're listing out our images here's dev that we built a little while ago 34 minutes ago and here's the prod right and now you can see this image side is only 16 megabytes right why is it so small because we did that multi-stage we said oh do all the heavy lifting up here go ahead and build everything compile it minify it observe obfuscate it um do tree shaking right all the code that's not being executed execute pass right get rid of all of it we don't need it right only give me what i need give me the output everything that's in this build file this build folder excuse me right and then start a new face i'm going to use a new base image the nginx based on the alpine which is a very slim image size copy everything from the build phase above it copy that into user share nginx.html expose port 80 and then run nginx that's why that's how you got a very very small image and that's why i wasn't worried about doing a docker ignore earlier and all those type of things you absolutely should do a docker nor but i didn't want to get sidetracked on that so you can see here's our dev image is one point uh one and a quarter gigabytes and right here about about 17 megs so huge difference nice small image okay that's awesome we got it built but you know who cares unless it actually works so let's run it so i'm gonna do a docker run i'm gonna use all the same things i'm gonna do i'm gonna get rid of mapping in our source code we don't need that okay let me run through these flags again so everybody understands so i'm doing a docker run that's the command we're running we're gonna run an image inside of a container that's what that's what you're doing when you're running that's the difference between an image and a container an image is a template uh is yeah is a template is set up packaged up it has everything in it it's ready to go and then when you run it in a container it's an instance of that image running inside the container just like an object-oriented program you have a class which is your image so you have a class and then you have an object which is your container your object is an instance of that class so you can have multiple objects of that same class so we've got a user class we go new user you know varjo equals new user var peter equals new user var sally equals new user right those are all instances of that class all running same thing with docker you have an image when we do a docker run that creates a container based on that image and we can do this multiple times so you can run multiple instances of that image inside of containers and that's how you scale and that's how you do um orchestration that's what kubernetes does swarm does you know all those orchestrators do okay awesome so we're going to do docker run so take that image right inside of the container we're going to give it a dash r it's a nice convenience when you stop your image running locally i want it to go away i don't have to don't want to do a docker stop docker remove um okay let me give it an it i give it an interactive terminal we're going to name it web we're going to expose we're going to publish port 3000 and we want to map that to port 80. nginx inside that container is running on port 80. we can change that you can you could change the configuration the nginx configuration whatever you need to do but it remember it's isolated inside of that container on its own network right so it can access port 80 not the same port 80 that's running on my machine so i'm going to i want to map publish port port 80 on 3000 on my local machine and i'm going to map that back in all right so we'll be able to access this uh nginx server using port 3000 in my local browser and then i tell it what image to use so react dash docker 1.0.0 dash prod the one we just built and if the demo gods are with us today everything should work just nifty so i played enter i don't have anything back okay let's test this out um let me ask let me answer something referring as prod in the second stage technically needed no harish it's not it's not technically needed so what harish is saying is down here when i said this is prod do you have to name the last stage inside of your docker file do you have to give it a name no it's gonna it's gonna run if you don't give it a target so when you when you do a docker build you can give it a target of what stage to use and these are hierarchical um so if i had other you know from uh let's do node let's just do nude as um you know local or or as dev right and um i copied everything you know you could add you could have multiple things here right so i can have another command here so this is this is a stage uh sorry this is a stage right this is a stage and one up here is a stage so when you run when you do a docker build you can give it what target to build and if i gave it let me get this out of the way so it doesn't confuse folks okay so if i did a docker build and i said dash target and i said prod what the engine will do what build x actually does looks at well the docker engine does this too so it'll look at prod and it goes okay what dependencies does it have it has build okay so i got to run build first so run build and then it'll run part prod but since this is the last one in the docker file and you don't give it a target that's the target that gets that's the default target right so yes we technically could have left that off there i like to label it because usually as you build these out you're going to have a build phase stage you're going to have a dev stage so that the original docker file that we built um you could use that as dev right so you can do docker build target dev and run that image locally right you technically probably uh you know could leave the production as the default so anytime anybody builds this outs you know builds it normally it will be built as a production image right that conic should be your default and then developers locally should build specifically with the dev target right great question okay a good question here so i've heard that the back end knowledge helps a lot in docker and devops stuff uh does it is it true and if yes which language you prefer to learn from um it it doesn't directly help in my opinion other than in um you know developers engineers software engineers that are working in the back end they do have to deal a little bit more with operation stuff right devops they deal a little more with servers those type of things right and therefore that kind of leads in the docker they're building images a little bit more right so that's probably why uh they just have a a little bit more body of knowledge that applies to containers and images and dockers right as where front end you might not need to do all those things just to build a um vue.js or react.js right but it they're not uh they're not directly tied so you could do a ton of stuff as just a front-end dev mostly in react you don't need to learn a middle tier back-end type of language um so no would be my answer um i think it's just because uh more back-end folks are dealing with servers right their code runs on a server right that type of thing um what language would i think if you're thinking about back-end if you're a front-end developer start with javascript stay in javascript go to node.js right learn it there learn how to build apis rest apis how to talk to databases get really good at um generally speaking as a software engineer the two things that you should focus on to progress as a software engineer is coupling and cohesion right so you want your code to be loosely coupled but highly cohesive uh i don't want to go into it right now because we're about an hour and 15 minutes but maybe i should do a whole show on that but um that's the two secrets outside of you know and those two things apply to procedural languages functional languages object-oriented languages they all are based on clean code which is based on cohesiveness and coupling you want your things loosely coupled and highly cohesive so cohesive means if i have a log module log writing module that log writer should only know how to be able to take logs and write them to a file and you can even split that out farther and say all what a log module should know about is how to grab logs at different levels let's say errors um warnings those type of things and then it should depend on something else or not depend on but should use something else that knows how to write to a file knows how to write to a database right and those should be loosely coupled but inside of that logging module it should know everything about logging and really nothing else right so it's cohesive to what it's trying to do separation concerns you probably heard about right and they're loosely coupled so i have my application that is loosely coupled with my logging mechanism right so i have my application i can tr i can plug and play different logging modules i could plug and play how they get written to disk or to a database or push to an api right so you want things that are loosely coupled and highly cohesive focus on those two don't worry about back end find a language that you can practice those in javascript's fantastic um second to that i would think about python and java javascript python and java is the top three languages i see out there in the wild not just myself but people that do um you know that actually talk to massive amounts of developers okay awesome question guys i really appreciate it um oh so we ran this did we not did we run this i don't know i can't remember yes we did oh we started it up so we ran docker run we gave it my my infamous rm i.t interactive terminal we named it as web put it on port thousand three thousand into eighty and then we told him what image to run and we said go for it docker run this image inside of a container let's jump over this command line let's do a docker ps ps there we go it's running what's up seven minutes ago wow answer question for seven minutes i appreciate the questions uh oh we're gonna talk about yes we'll talk about cache layers in a second but let me finish this up okay so now we we did our multi-stage uh build we produced an image that only has nginx in our html css and some other stuff that you guys saw in the build directory so let's go back to our browser um let's do 2001 so we see we get a nice blank screen so let me go to port 3000 and there we go ready like a champ and there you go you see all your nginx uh logs there we go everything is inside there we have a production build it has just our minified obfuscated code inside of that image running inside of a container now you could pass this one around and whoever your ops devops whoever you have you know maybe even someone else on your team can run this in some kind of orchestrator they can run it in ecs aci eks you can run it on an ec2 instance with a docker engine running that is 1 000 a good idea right if you're running if you're working at a smaller business or doesn't matter size of the business if you build an application for a company that has five users in the accounting department that use your application you do not need kubernetes you do not need swarm right you don't need an orchestrator you can set up a digital ocean compute instance have docker engine running on it and run your container right there very simple before i came to docker we did that for all of our clients ran really really great all right here we go one more question here uh dataveer i'm probably pronouncing that wrong forgive me hello peter any advantage we use an nginx server uh we could write an express app and say node server yeah absolutely um you know what i like about using nginx or you know another uh web server is you know separation of concerns again nginx is a fast powerful web server that's been built to do just that right serve static files extremely fast uh and can scale really well right um so that's why i like to use it but yeah absolutely i did we also did that for many years i wrote i probably still have it laying around um i actually didn't use express i just wrote pure javascript right a little web server that um you know look looked at the url read it off a disk and sent it back right so yeah so you know if you have a little express app uh that that handles serving up your files absolutely you could do that um i just think nginx in a production environment it was milt was made and built to do just that and has been tested by millions of uh you know instances running in the world so that that's my thought around that but there's nothing inherently wrong you know uh yes if you build a express app or you have a web server that you really like use it right use it okay awesome so that's what i have for you guys today um i know we went over a lot i hope you enjoyed it uh let me turn off my sharing here um stay tuned uh we're gonna do a follow-up i'm going to take so we looked at a little bit of developing inside a container we have some new features coming out called dev environments they're in uh our product right now they're in a in a dev preview go play around with them i'm going to show you how you can use dev environments to do a little bit of what we just did um so you basically can point at a github repo pull it down everything will be set inside of containers and it actually wires up into your vs code so you can start coding you can start debugging right away and then you're able to take that dev image and share it with a co-worker who can pull it down see exactly where you're at in your code your environment your configuration and uh maybe edit a pr review a pr make a change for you share that environment back with you and you could take a look at it stay tuned for that we're gonna have more uh content around that again thank you everybody for joining me i really really appreciate it um let me get my uh my ctas i like to do it the end so give you a little bit of help first of all please connect with me on twitter reach out to me uh tweet at me um let me know you have any questions let me know what else you want to see on the show if there's something that you want me to cover if you want to go if you want to do a vue.js or an angular the concepts we went through are you know exactly the same we can do an advanced uh front-end containerizing an application right you might have things let's say configuration right where i have my front-end app and i need to know where to point to call my apis and that might be done environment variables configuration those type of things but again at runtime on the server your react app is not being processed to change configuration and put it down right so anyways let me know tweet at me follow me also to go out to join our developer community uh the url is right there you can see what meetups we've got going um i think we believe we have a community all hands coming up check that out uh and then also join our community slack uh i'm on there a lot of our engineers are on there our product folks are on there um you can interact with us our community is huge it's very active on slack you can ask your questions people in the community captains are docker captains which are our experts out in the field that are actually working at companies like you day-to-day hands-on with docker they help us out in slack they're fantastic you can interact with them and then also check out our roadmap on github you can see what we're working on you can see what we have planned you could see when things should be done uh create issues in there if you want to see a feature for docker docker desktop docker hub put them in there we do read them we do interact with you great way to get involved with docker and help direct uh the direction of the company all right everybody thank you so much i really appreciate you joining i hope you enjoyed it and we'll see you next week take care
Info
Channel: Docker
Views: 29,752
Rating: undefined out of 5
Keywords:
Id: 8VHheCkw-7k
Channel Id: undefined
Length: 81min 51sec (4911 seconds)
Published: Thu Jul 22 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.