How to Speed up Docker Development! 🐳 Hot Reloading, Debuggers, and More!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
containers are often touted for their ability to make deploying and operating software applications easier and more reliable those are both valid points but when developing with containers it can be confusing to get started and unless you configure things properly the development experience is quite frustrating in this video i'll demonstrate how to work with a containerized node.js application setting up hot reloading utilizing a debugger and wrangling with the complexity of all the various command line flags at the end of this video you'll be ready to get to work developing within containerized projects hey team sid here with devops directive where it's my job to help you level up your devops and cloud infrastructure skills if you're into that sort of thing go ahead and subscribe for more videos like this one without further ado let's jump into the code the sample application that i'm going to use is a hello world api written in express.js so it's node.js based as you can see it takes up just 11 lines of code here the only dependency is express and we're using a fairly straightforward docker file we start from the base image install express with the package.json file we copy in our source code and then execute the app if you're brand new to containers i would suggest watching this video by jake wright learn docker in 12 minutes as a starting place and the rest of the video will make a lot more sense after that now let's say this was a project that you were just getting started with the first thing that you would want to do is build this container image and then run the application so i can bring up a terminal here and do docker build dash t i'll tag it with the tag hello world express then the period specifies my current directory with that built i can then run it with docker run i want to port forward port 3000 because that's where the app is listening so this will allow me to send connections from my macbook into this container and then give it that name hello world express now the application's running on port 3000 so if i issue a request in the browser we see it respond with hello world let's say we wanted to make a change and instead of hello world we wanted to now say hello youtube one of the main frustrations that people have when getting started with docker is that because the container has an isolated file system from your host system from your laptop or desktop that you're doing development on you would have to rebuild the image every single time you want to make a change so let me just build and run this image as a starting point to show you what i mean i would go into the source code i would update this line but just updating it there doesn't change anything about this container and i can reload it still it says hello world in order to have that reflected i would need to stop that container from running rebuild with this command and then rerun now if i refresh the page we get the updated message as you can see this development workflow is terribly slow if you're used to working with node.js you're probably familiar with a package called nodemon which monitors your file system looking for changes and will restart the node process if it detects a change we can use this within a container but it takes a little setting up to do let me show you how you do that the first thing that i'll do is go into my docker file and here before i install anything i'm going to install nodemon into this container image i can issue a run command and then yarn global add nodemon so now when i build this container image it will install nodemon before it installs any of our other dependencies let me go ahead and rebuild the app now i can issue a run command like before i'll append a new command so by default my docker image is going to run this node server.js instead i can pass it nodemon server.js however there's one issue with this if i pass it as is the docker container can't actually see changes to my host file system so i'll need to use what's called a volume mount i can pass the dash b flag to mount in my present working directory into the container at my working directory here of user source app this way when i make changes on my local file system it will be reflected inside the container however the issue with that is that because we have this node modules directory here in our host system that's going to get mounted in as well overwriting the node modules we installed when we built our docker image to fix this i can actually add a second volume mount where i just mount an empty path for my host system so i don't even include anything on the left side of the colon and that'll just be slash user source app node modules then i'll issue it that nodemon server.js command as you can see nodemon starts up we can load our api now let's add a couple more exclamation points save it and we see that even though this file is on my host file system nodemon inside the container detects the change reloads the server and now we can see that reflected in our api response so just like that we can get hot reloading working just like you would to developing locally inside the container doing this will speed up the iteration time for developing these containers immensely the second thing that i want to show you today is how to set up using the node.js inspect debugger inside the container so i'll kill this app so normally to use the debugger you would use something like node or nodemon dash dash inspect and then server.js and this would run an additional process this would run an additional server on your localhost that you could connect to and get additional information from node.js about the application that it's running however inside the container the configuration is a little different so let me walk you through that we're going to issue a command similar to what we did before but now we'll issue this inspect command we need to actually pass it an address of 0.0.0.0 on port nine two two nine it's the default port but if we just ran that we wouldn't actually be able to connect to this debugger uh we need to additionally port forward that port from our local system to the container and this 0.0.0 address ensures that it's reachable from outside the container when we make those requests now if i issue this command we've got our app listening on port 3000 but we also have an additional debugger listening on port 9229 i can then open up my browser and in a new tab type about inspect open dedicated dev tools for node and this gives me a window where i can where i've connected to my application and now i can do something like add a debugger line my app is restarted my debugger is attached if i now make that same request the program execution actually stops at that break point i can see the state of all these variables i can step through over to the next we can see that it has jumped onto that line and then i can allow it to continue on and so this is great and now we have hot reloading working we've got our debugger working but this command is super gnarly we've got all these command line flags we've got multiple volume mounts there's no way that you're gonna want to have to type this out every time one option would be to store that command off in a make file however i think an even more powerful technique is to use docker compose and so docker compose allows us to specify a configuration file in the form of yaml that can specify all these parameters and more and encapsulate that such that we can run it the same way every time so let's create a quick docker compose file for this application for our development environment so we can start by just specifying the docker compose version i'm just going to use the latest minor version 3.9 and then we specify the different services we want to have in this case we're just going to have one service for our api server you could also have your database service defined here a front-end service and then this way you can compose multiple containers as the name implies into one single application i'm going to call our service express and then i'm going to use the build directive and i'll give it a context and just pass it the current directory so that will tell docker compose to build the files in the current working directory we then want to specify those same ports that we had before so we want to mount in 3000 and 9229 so we can do ports three thousand three thousand nine two two nine nine two two nine we'll add our volume mounts so first we're going to mount in the local directory into user source app and then again we're going to have that empty mount so that we don't overwrite our node modules inside the container we can specify environment variables here so this i didn't talk about before but it's super useful so we might specify for example node and equals development and then i'm going to specify the command that i was passing there at the end so this will be my nodemon inspect server.js great and that should be it and now if i go back to my terminal i can just do docker compose up this used to be one command you had to have a dash between it they have since added it directly to the docker cli so we can do it like this it will rebuild my image because i have this build directive it will then create my application it will then create my application container and we can see it running here and i'm actually going to go modify this and this will be hello world from docker compose container as you can see saving that file we get our container restarted the volume mounts are working we will go here and make a request and we should see it hit that debugger breakpoint great i'll let it continue and then we get the updated message so all that functionality that we were building in with these long commands is now encapsulated in this config file that's much easier to parse and understand and share with your teammates these are the things that i wish i knew when i was first getting started with containers hopefully they'll make your life developing containerized applications significantly easier if you like the video go ahead and hit the thumbs up to let youtube know and if you want to continue down the devops rabbit hole i'd recommend checking out one of the other videos over there and remember just keep building [Music]
Info
Channel: DevOps Directive
Views: 26,350
Rating: undefined out of 5
Keywords: docker, container, devops, developer experience, nodemon, express, expressjs, nodejs, node, docker container, docker tutorial
Id: 5JQlFK6MdVQ
Channel Id: undefined
Length: 13min 31sec (811 seconds)
Published: Wed Aug 18 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.