Ultimate Typescript/Node/Docker Setup: Step-by-Step (2021)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there folks today we are going to walk through how to get node up and running in docker along with a lot of the popular other tools that you might need alongside that i'm going to use typescript in this demo and we're going to get eslint set up prettier prisma for connecting with the database we're going to get postgres running in docker database migrations and all of that integrated in with vs code as well and enabling debugging nvs code even with your node app running in docker so without further ado let's get going by the way too i've created a blog post uh with going through every single detail uh that we're gonna go over in this video so if you want a place to refer back to or maybe a place to copy and paste some of the code or configuration then i will put a link to this in the description of this video but let's get started so we are going to start from absolute scratch here we're going to go step by step and really go through and explain each of these uh steps and choices along the way so let me let me go ahead and get into a good uh repository for me so the first thing we're going to do is just by hand create an empty directory and i'll just call this a node stack and then we'll cd into it and i'm gonna use yarn and knit here to go ahead and initialize this uh as a npm or yarn package and i'm basically just going to hit enter down here for each question essentially essentially what this does is create a package.json file for us to get started so if i do code dot so the first thing we've done is we've created this package.json file with the yarn init command and that's just created a very simple uh package.json file for us so what i'm going to do is i'm going to open up the terminal here within vs code and the first thing we're going to do is add typescript to this project so i'm going to do a yarn add typescript and that will add typescript as a dependency to this project and get everything that we need and then if you've done typescript before you know that we'll end up creating a tsconfig.json file in order to configure our typescript environment and there's a really great package that's officially supported by typescript and i suppose microsoft themselves that gives you a set of recommendations to add in to this configuration to use in your project and along along the way through this walkthrough i'm going to try to use as many defaults and recommendations as possible to keep this a good baseline stack to get your app started so i'm going to do a yarn add and we're just going to add this in dev uh from ts config slash node 14. and so this is a package that will that we can extend into our ts config now i am actually using node 15 in this uh demo because i'm on an apple m1 chip and node 14 isn't compatible with uh with the m1 chip so if you're doing a production ready application or production focus application i'd probably recommend going with the latest lts your latest long-term support version of node which is currently 14 but i'm on an n1 so we're going to go 15. so let us create a tsconfig.json file in the root of our repository here and this is going to allow us to configure our typescript application and because we're in vs code uh then we get a lot of nice uh completion for us uh in this configuration so we're going to say extends and we're gonna bring in that ts config slash node 14 tsconfig.json so this will bring in those recommendations from the official ts config recommendations then we're going to set a few compiler options here and the first thing we're going to do is set uh lib this will allow us to use some of the newer javascript features within typescript and i'm also going to set up an out directory this will tell typescript where to compile the code to i think by default it compiles it in the same directory as each of the source typescript files but i want to i want to compile everything into a directory that i'm calling dist here then a couple of other things we're going to tell typescript which files to include and we're going to create a source directory so i'm going to add that here and then finally this actually isn't going to be used in this project but i frequently use jest for testing in node applications and so i'm going to say to exclude any files that end in test.ts so if we were to add some tests in here using jest then we don't need to compile those into our production ready build so with this ts config.json we should be set up to use typescript in this project so let's get started by creating a our first source file so i'm going to go through source index.ts and i'm just going to do a very simple very simple console log hello world and uh this might throw you for a loop uh the first time you see it you're like why first line of code why am i already getting a red squiggly um that's because we need to actually add in a types or typings file for node itself so uh there is this awesome project called definitely typed which has a bunch of community supported community driven type configurations for things that don't naturally have types of built into typescript so i'm going to add do a yarn add dev here i'm going to add the types for node so all of the definitely typed types begin with this at type slash so for things like low dash you might do an at type slash low dash to pull in the types for low dash since that is one of the many packages that don't have typescript types built in and here we go so now that we have this installed vs code has recognized that it's kind of reloaded things here and we don't have this red squiggly anymore um one other thing i'm going to do and if you watched my calculator video you saw me hit a brick wall on this one but it's really important to set up which typescript version you are using in your project so if you have a typescript file open here i'm going to go ahead and save this if you have a typescript file open here you can click on the version number and you can actually go here to say select typescript version and you can choose whether to use the vs code version which is a terrible idea or use the workspace version and that's the version that we installed with our yarn add typescript at the very beginning so i'm going to say to use the workspace version here and what vs code is going to do is it's going to create this new directory called dot vs code and it's going to save any project level configuration here within this directory so if i open up settings it is specifying that the typescript sdk should be the one that we have installed in node modules so what that means is it's the one installed that we specified here uh as our dependency in package.json so a couple of you know several different things here to get typescript going but i hope that this is helpful to walk through uh because it can it can get a little trippy sometimes so i believe that's all that we need for typescript let's set up a build process now and actually build our little hello world here and see if that runs so what i like to do is set up a script within package.json to build this build this for me so that i can go into any of my projects and do a yarn build and whatever build steps i need to take place then that's built into the build script within package.json so before i do that i'm actually going to add another dependency i'm going to say yarn add to your dev dependencies rimraff this is essentially a javascript way of doing an rm rf to completely blow away a directory so why i'm doing that is because in our scripts folder when i define a build script here what i want to be able to do is blow away that previous build that i had of our code so if you remember back in our back in our ts config.json we specified that we want our out directory to be dist so what i'm going to do is i'm going to do rimraf dist so that'll blow away our disk directory and then i'm going to compile our code so i'll do a tsc for the typescript compiler and this will be available because we have typescript as a dependency so if i save this then i now have this build script available for me so if i go down here and i do a yarn build what should pop up here is yes we have a new disk directory and we have index dot j uh dot j s so if i pull this side by side with my index.ts here's index.ts on the left and the next.js on the right they're pretty much one for one is aside from this uh use strict line up at the top so we we do have our typescript compiler working it's compiling to the dist directory um and we've got that going excellent now the next thing i'm going to do is i'm going to create a start script so that we have a common way to start this application so let me go back into package.json and i will add a start script here so for now what we're going to do is we're going to say node and we're going to run the file that is built in that dist directory so we're writing typescript then we're going to compile it build it into our disk directory and then that's where we're actually going to run our code so i'm going to save that so if i go down here and do a yarn start then there we go we have our hello world so officially we are running in typescript land now so that is great now um we're not running in docker yet we don't have a database we don't have eslint we don't printer we don't have all that stuff yet but we'll get there so this is probably a good time to go ahead and make this a git repository and commit some of our changes in so i'm going to go i'm going to close all these windows and i'm going to create first a dot get ignore file so i can tell get what it shouldn't store in the repository and frequently for javascript applications there are at least two things that you want to be sure and include in here first is node modules there is absolutely no reason and you should definitely not check in your node modules into your git repository and then the second one here is i'm going to actually add our dist directory we don't want to check in our distribution or build files into our github repository because we want those to be built whenever a container is built or when this is deployed to production or something like that so i'm going to hit save here and then from the command line i'm going to run a git init so we've initialized a git repository at this location and i'll do a git status so we can see what's going on and we can see that it's it it hasn't checked in and it has available the git ignore file uh the vs code directory is showing up here and this is something you do want to check into your git repository because it's a way for you to share configuration uh and settings and recommendations we'll get to here in a minute with your team definitely want package.json source ts config and yarn.log those all look good so i'm going to do a git add a here to add all these files or really stage all of these files and then we'll do a commit and there we go so we have now uh we have now uh initial commit with some progress that we've made getting typescript up and running so the next thing i want to get up and running is uh an e in is eslint um you may have heard of there's both eslint out in the wild and tslent tslent used to be what a lot of the typescript was community was using for linting but eslint even for typescript is now their recommended way to go so that's what we're going to do here and we'll install the things that are necessary to get typescript working or eslint working with typescript so we'll do a yarn add dev because we really only need linting in dev and we'll add eslint but we will also checking my notes here we will also add in from the typescript eslint project um the eslint plug-in at latest and the typescript eslint parser at last so with the eslint the typescript eslant plugin and eslint parser then that's what we'll need to get typescript going with eslint plus a little configuration so we have our dependencies installed now let's create an eslint a dot eslint rc file and you'll frequently see something something something rc within the root of a project for configuration files so the first thing we're going to do here and we get some nice code completion is we're going to extend uh other configurations so the first thing we'll do is bring in the general eslant recommendations so we can extend eslint recommended so this will piggyback off of what eslint themselves recommend for your configuration and then we'll add in our plugin that we just added which is typescript eslint slash recommended then in order to get this working with typescript we have to specify our parser which is typescript eslint parser and finally we'll add our plugin of typescript eslint now this is a whole lot to remember and frankly you don't need to remember it um you can check out the documentation for typescript dslr or like i said i have a blog post with all this that i'll link to in the description but this is really kind of a set it up once sort of thing for your project so that that is what we need to get going for eslint now me personally i don't typically add linting and we'll get to prettier here in just a moment to the build process um it's just not my cup of tea i prefer to have all the linting and code formatting done just in my editor i don't want it slowing the build and i don't want things changing after i save them either so you could go either way on this however you wanted but i'm going to rely on vs code in to really handle the linting and display any warnings or errors to me so let's move on to prettier for prettier i i don't actually need to install any packages instead i'm just going to add a configuration so i'll add a prettier or a dot prettier rc file again that's configuration and what you might want to start with is just empty curly braces here just to get the default configuration now me personally i am for some reason for some reason attached to single quotes so uh i like changing my projects over to single quotes and but that's the only one that i change i used to get rid of trailing commas but uh i gave in on that one i'm i'm all for trailing commas now so that's fine so this is what we need for eslint and prettier now i i already have some packages installed um in vs code to handle this for me but if you're working across a team or maybe you're prepping for your future self when you my open this back one day it's a good idea to configure in here some recommended packages that your other team or your future self could use for this project so if i go to my extensions here and i search for the prettier extension that i have installed it has this little kind of a reference tag to it typically it's someone's username and the name of the project and what you can do is you can take this and up in your vs code directory here you can create what's called a an extensions file so that's what we're going to do here and we're going to add recommendations that we recommend for this project so i'm going to and you do it by that reference so i'm going to add in the prettier vs code recommendation and i'm also going to add in the eslint package that i have here so when someone opens up this repository then vs code will pop up and recommend that they install these packages they don't have to it's not forced or required it's just recommended so here we go now if i go back to we'll test this out now if i go back to my main file here and i make a const you know unused variable one two three then i will get a warning that this a variable this variable is assigned but never used so that is showing me the eslint is working here in this project so we have typescript we're building we have eslint we have prettier and we've even added some recommendations for extensions so now the next step is i'm going to go ahead and get a a web server running in here and then we'll jump into dockerland so the most popular web server i think out there for node is obviously express and i've used express for most of my projects in this though i've been interested in uh fastify lately and uh it's just something i'm uh interested in using and learning more about i'm very familiar with express but i'm interested in getting to fastify and it does have some pretty nice benchmarks as far as its speed goes hence its name so let me undo some of this and we will do a yarn and fastify again fastify and express you could really interchange these but i'm going to use fastify in this example so we'll install that and then what we'll do i think my code might have froze let's see here see if it comes back i think my vs code might have frozen okay let's hit reopen that was weird okay let's see if our package.json actually got it did not get that dependency so let's try that again let's do yarn and fastify there we go so let's go up to our source index file and we'll mock out just a very basic web server here in fastify so first thing we'll do is import it and just like express you end up making an instance of that so um i'm gonna say app equals fast i'll i'll call it fastify fastify equals fastify and we will use the logger now their default logger is in json format which is really interesting to me i know that that would work well if you're pumping your logs into something like datadog or elasticsearch or something that you could then analyze but they have they have various other logger options that you could check out and just like express you can define routes so i'm gonna say dot get uh at the root and you would get uh very similarly a uh i believe it's a request response uh like express we're not going to use those we're just simply going to return uh we'll return a json object with hello world there we go and then finally let's start our server so i'm going to define a port variable here and i'm going to add a default but also listen for an environment variable that might be coming in called port so i'll do process.m.port or 8080. now you might see have seen uh the double vertical bar or before um that's a true or this i can't remember off the top of my head what what that's called but it's essentially an operator to detect presence so if this is not present then it will use 8080. then we'll create if you look at the fastified documentation they actually recommend creating a start function and in a try catch we will await fastify.listen we'll listen on our port and then uh finally we will catch that and we can actually log it via fastify and then finally exit the node process if there is an error and we'll run this start function at the very bottom the reason we have to make this a function is because you can't yet do top level weight in node now this will work locally this is great but there's one other thing i'm going to do and i'm kind of planning ahead a bit here when it comes to docker whenever you're running a web server inside of docker by default most web server packages like express or fastfi will bind to localhost they'll bind to 127.0 to zero to one in docker you need to bind to 0.0.0.0 so i'm going to specify a second argument here which is specifying our zero to zero to zero to zero host so again you don't really need that just for local development um right on your machine but once we put this into docker you definitely will so i'm planning ahead of it there so let me save that and we're going to run this locally just to make sure that we don't have any glaring mistakes yet so i'll do another yarn build so that will clear away what i had in my dist folder recompile if i open up my index.js now i can see some code starting to come to life here this is what typescript has compiled uh my code into so now let's do a yarn start and i can see that we we have some logging here this is the fastified logging format and it looks like we've started our server so i'm going to add another terminal window here this nice little button splits the pane and i'm just going to curl localhost and i didn't pass in a port so it's 8080. and there we go that's hello world so we have our fastify server up and running but we're not yet in docker so we've finally arrived we have enough going for us that it's time to get going on docker now uh excellent now what everything we've done so far has been about writing the code building it and starting it but no one wants to do that in development you want all this to auto recompile for you and we want that to work inside of docker also so we're going to do a couple of different things here the first thing we're going to do is we're going to add a package called ts node and we'll add that to our dev dependencies ts node helps you to compile typescript kind of on the fly um it's much like running the node command if you might have had a node.index.js file you can't run node typescript because that's not native to node but what you could run is ts node index.ts and that would on the fly compile the type script for you and just make things a bit simpler so we're going to use ts node here in conjunction with docker so we've just gotten our ts node dependency added so now we'll get into the docker stuff we will add a docker file to define how to build this container in docker so the first thing we're going to do is define our base image here and many of the popular tools and components that people use have really awesome base images there are postgres images redis images elastic search um node which is what we'll use here so i highly recommend that you go to uh docker hub and check out uh these base packages so the one we're gonna add today is node so i can just click on the node here the other nice thing about going to docker hub here is you can see if this is an official image or not of course you don't want to be running unknown code and unverified code on your machine or in your container so using the official images is always nice so we'll do node and then uh if you go over to the tags uh there are all sorts of tags that you can use this is what i'm thinking yeah this is a different view than i'm used to um there are all sorts of different tags that you can use for things like various versions so i'm running node 15 locally so if i search 15 here then i can see there are all sorts of various tags i thought there was a different view oh here we go this is what i was thinking so these are a bunch of different tags that we can use so i would recommend starting with your major versions so we're gonna go for 15 and if you wanted to specify a minor version two you you could do that as well so maybe fifteen five uh and then what we're going to do is we're going to say that we want to use the alpine version and alpine is a very slim version of linux it's great for running in docker where you want to keep your resource usage really low so we're going to do 15.5 uh hyphen alpine this is what we're going to do 15.5 half an i alpine so if you're watching this from the future you may be installing oh auto completion you may be installing just a different version number here so we'll start with this base package and the first thing we'll do is we will set up a working directory so i'm going to add a directory and user source app and this is going to be where we copy our app into in docker but before we copy it in what i'm going to do is i'm going to copy just a few files so i'm first going to copy the package.json file into the root of this working directory and i'm also going to copy our yarn dot lock file into the root and then i'm going to run a yarn install the reason i'm only doing these two files at first is because of the way docker works docker runs one line at a time and caches the state at each line so if you have something that updates later so if we update our source later but we don't update uh package.json or yarn.lock it could actually cache the state of this build before moving on to future items that might have been changed like any of your other source files so we'll run the yarn install there then we'll copy everything from our root project directory into uh our docker container then we'll do a run yarn build and that will build our app inside the docker container expose port 8080 and then finally we'll define a command to run at the very end which will be yarn.start i don't really know why but for some reason you have to separate out each command and argument in this list format not sure it's probably some windows versus linux thing i don't know here we go so this should be the docker file that we need to get our app going and uh that looks good now what we don't have here is yeah i think this will work so one other thing let me look at something here so that's our docker file now what we're really going to do is we're going to define a docker compose environment that will create our definition of our entire project so for this project we want both and a node server but also a postgres database server and we want to be able to recreate those in a predictable fashion so i'm going to create a file at the root here called docker compose docker hyphen compose dot yaml and this is a way to define um a docker environment so we will uh it's in yaml format so we'll add a services uh block item root level uh object here and then underneath that we'll add each of our services so we'll start first with web and that services is actually a docker compose keyword and then each service can be called whatever you want it to be called so we'll call this one web and we're going to say build the current directory and what that will do is it will look for this docker file here in our current directory then we're going to define uh what ports we want to both expose and map to our local system here so i'm going to expose we're going to run this on port 5000 um that will be good and then the other crucial thing here and again we're doing a little planning ahead but i want to expose port 9229 a magical port that will allow us to use the vs code debugger a bit later even with our node app running inside docker so i might even just make a little comment here that this enables debugging later so those are our ports uh the next thing we want to do is uh add volumes and this is something i always have to look up from one of my previous projects and that is how the volumes work so docker compose volumes do at least two different things one is we're go we want to have the source repository on our local machine really be the same as inside this docker compose container so that we can have really fast development locally we don't want to have to change a source file rebuild our entire container every single time just see those changes take place so docker on your local environment allows you to map those directories together so that the your project directory here on your local machine and inside the container can really be the same thing so i'm going to map the current directory signified by the dot here to the same thing that i had in my docker file earlier um defined as my working directory so i'm going to map my project directory to this directory in the container the other special thing uh that volumes do or maintain some sort of consistent state between runs and after we map this app directory i'm also going not this isn't a mapping but this is just defining a volume i'm defining a volume for our node modules so we can separate out a bit the node modules that are inside of our container versus the node modules i have here on my local mac because the builds might be slightly different my mac's running mac and mac os and the containers running alpine linux so we want to keep those separated a bit then the other cool thing that you can do in a docker compose file is you can actually change which command that we're using to start the server now i kind of breezed over this earlier but the command we're using here is yarn start and i'm going to open up yet another pane here if we remember the start command we used is the command that runs node from the dist directory and that's great for production so this this docker file i've really written it to be more of a production doctor file but for development again we want rapid development so instead of having to compile each time and even worse rebuild this entire container i want to do something that will allow me to quickly um apply code changes so i'm going to change the command command so instead of running yarn start i'm going to run yarn dev and we'll define a dev script here in just a minute and then finally i'm going to define what i want my port to be so you can pass in environment variables and i'm going to add this to port 5000 to match the port i'm exposing above again these ports can be anything you want 9229 is a special one save that for later but 5000 here you can run this four thousand three thousand five thousand what whatever you want here so this is good but now i need to add this yarn dev command uh in order to uh run our server so let's add a dev script here and instead of running the file from the disk directory via node instead we're going to directly use ts node which we added as a dependency earlier and we're going to directly run that on our source typescript file instead of the one in the dist directory so there we go that should be what we need to uh run this code so i think we should try it let me close out some of these let me open up my terminal again and what we'll do here is we're going to run docker compose up let's see what happens oh i don't think i saved save hey there we go so um it looks like it looks like it saved a build of mine from one of my tests from earlier that's cheating so uh let me go ahead and run something special here to uh remove my web container and [Music] go up okay this is saving something i had from one of my tests earlier what what you should actually see when you run this is uh i'm gonna run a build here but when you do a docker compose up it's going to go through and build your docker file for the first time running through each of these steps you'll probably see it downloading this version of node if you haven't downloaded that before it will go through copy in your package.json your yarn.lock install those dependencies copy in your project build it into that disk directory inside the container and finally expose the port so we're building our web uh container here again you don't have to you likely won't have to run build right now you probably will later um i'm running that just to override one of my tests from earlier there we go so now let me do a docker compose i'm gonna just double make sure that i removed all the stuff and docker compose up here we go so it looks like everything's started i'm going to open up another terminal here and again i'll curl now what will i curl i can still curl my local host because of this port mapping above so this is saying that port 5000 on my local host will map to port 5000 in the container so here we go and we still get hello world so this hello world is coming from our fastify server running a node running in our alpine container in docker orchestrated by docker compose so that's a big win so far that's really great now let's get into a bit of developer happiness now what we want to happen here is when i change my code i want everything to auto recompile auto restart my server for me so instead of hello world if i do hello kevin here and hit save and then i go down here and i curl this again it still says hello world that's not what we want uh i'd really like for this to auto restart now there's a really popular library that a ton of people use called nodemon this is node monitor and it will monitor your local file system for any sort of changes nodemon's a great project and if you're developing on a local mac or windows machine excellent go with that in docker um you can use nodemon but you have to use uh the legacy watch flag because you're not able to from inside docker use the tools it needs to detect file system changes in an optimized fashion now legacy watch is uh as it says here a last resort because it has to pull every single file all the time to detect change and that will really eat up your cpu your battery life i think i've literally killed a laptop battery uh because of this flag uh so we're gonna do it in a bit of a different fashion now if we think about it via since we're editing our code in vs code here it knows about all of our file saves and it knows when things change so one approach might be to actually use vs code to upon every file save give our docker container a little kick and restart it so that's exactly what we're going to do here there is a extension that we can install called a trigger task on save so with this extension you can trigger a vs code task to happen tasks are native to vs code but triggering it on a save is what we'll use this extension for so i'm going to take this extension and i'm going to add that to our recommendations list so that other devs get prompted to add this whenever they open this project then i'm going to go in and i'm going to create a inside vs code a tasks.json file um in order to define some tasks here and we'll say that it's the latest version of this tasks schema and then we'll define our array of tasks so the first one uh actually the only one we'll have here is we're going to we want to restart uh our web container so if i open up our docker compose file um i named our web service web i could have named that node i frequently use back end in some of our projects i'm going to say restart web and then let's see if i do a control space here let's see what else we have there's a type shell so i want to run a shell command and then i can define what that command is so we'll do a docker compose restart web so if i do docker compose restart web then that will restart the web container and then there's another nice little option here called presentation and we really don't need any of these here we want presentation reveal never what this will do is when you run a task typically a window or a pane opens up here in vs code but we don't want that to happen automatically we're going to be saving all the time so i don't need that to happen so we will hit save on that so all this does so far is define the task now we need to define that trigger which is triggering it on file saves so i'm going to go back to our settings.json file here i'll move our tasks over here and we're going to add a setting if i search for trigger task on save this is going to show me the settings for that extension that i've installed called trigger task on safe and we're going to trigger the name the label of our task that we just created so this is called restart web and we're going to trigger this on any file save to any file within the source directory and there we go um there's also this interesting um exclusion [Music] exclusion list that you can add here to exclude these files from being watched as well i don't need it to watch all the files in my node modules or get uh hg i had to look that up i think that's from mercurial if you use that instead of git uh which i don't so i'm gonna delete that here so with this command set uh i've again i've installed the trigger task on save extension i've created a task that will run this command to restart my web container and then i've configured that task to run on every file saved from every file in my source directory so let's check this out let's close all this and i'm going to go in here to index.ts and i'm going to say hello docker and when i hit save what i expect to happen is that this web uh will exit uh since it's the only container running i think my whole docker compose log will exit here but we'll bring that back up so i hit save okay that's what i expected uh so the node stack web container exited now i want to let me let me run a docker compose ps that will show us our process list and we do actually have a container running that's up in the background so i'm just going to do a docker compose up again and that will attach itself to that container that's running so if i do a curl 5000 i get hello docker here so again um if i do hello docker compose i hit save uh i wait just a bit then there's hello docker compose now this is exiting here in a moment when we add postgres uh this log will keep going uh since we have more than one container going and that'll be a bit nicer so to recap so far we have typescript we have eslint we have prettier we've built a very basic fastify server uh we've added a docker file to build our project we've added docker compose to compose these uh compose just our node piece together actually so far and we've added all these script settings extensions and config along the way to get that going so that is that feels pretty good but let's keep going here we definitely want to enable debugging we want to be able to use the built-in vs code debugger in order to do debugging even when our node app is running within docker so we did one thing that was crucial earlier and i'll i'll just remind you of that and that's using that's opening up this port 9229 this is the default node inspect port you can customize this with flags in various places but i'm going to use the default one here but we also need to start node up with that debugger with that inspect available and if i just on my local terminal here do a node h for help i can see a whole bunch of things in fact that's kind of hard to see let me do that here if i do a node sh for help one of the options is inspect so you can add the inspect flag to activate the inspector on a given host and even on a given port so here's here's where you might put a custom port but we don't really need to so what we'll do is we need to edit the command that we're starting our node app with in the development environment to enable that inspector to run so i have my yarn dev command let me open up package.json where that's configured and dev is running ts node with our source file now i've already looked at the ts node documentation they don't have an inspect flag or argument that we can pass in so we'll rewrite this so that we can go back to the node executable but still use typescript so what you can do here is we can run for dev script we can run node but at the very top of the execution here we're going to register um ts node so that it can compile our code on the fly then we'll add in that uh very important inspect option and normally if you're just running this locally you could pass dash dash inspect and you'd be fine but in docker like i said uh we definitely have to bind everything 2. to that 0.0.0.0 port so with this inspect flag that we've changed out our dev script to be and with that port open in 9229 then that gets us a good bit of the ways there but that's just on the docker side now we need to configure vs code vs code allows you to if you go here into the run tab it allows you to configure how to run your application and debug it as well i'm going to do this a bit the manual way and i'm probably going to end up just copying in this configuration because it's a whole bunch this is honestly the thing that tripped me up for the longest time there's a ton of config to get this right and it's again one of those things you never have to change or rarely have to change but getting it right can be really really difficult so i i hope this helps you as well so in your via vs code directory we're going to create a launch.json file that's where we define uh all those launch configurations for running and debugging our app i'm actually gonna hop on over to the blog post that i've prepared and copy this in because uh again uh it's it's quite a bit here in fact i'm just gonna copy this here so this is the configuration we need for uh enabling debugging a bit wild but copy it in and you're done um we'll run through this though uh and see what we have so what we're doing is we're defining a configuration uh for vs code uh the type of this is node and this is very important so the type of request here we what we want to do is we want to attach the node debugger to or attach the vs code debugger to the node app that's already running in docker we don't want or need vs code to start something new for us so we want to it that's why we've put attach here this is just the name for what we're going to call it in this drop down you could have several different configurations here using the inspector protocol here's that 9229 port restart defines that if our node session terminates should the debugger restart and this is a super helpful uh option based upon how we are doing auto restarts on any source file changes so if you change a source file the node instance will die that docker container will get restarted and with this option the debugger will go ahead and reattach if it was attached before and then this this is what tripped me up for a long time uh getting the right mappings between the directories in the docker container and the directories in your project file getting source maps compiling correctly just take a look at this and add it to your project uh but this is this is much of the crucial configuration here so now that we have that configured we have our port open we have our dev script going uh let's try this out and see if we can debug it so i will go into docker compose run up i can see that this is still running our old command so in our other window here i'm going to do a docker well actually i'll just uh control c out of that which will stop the container and we'll run up again here we go so that is now running our newer command that we defined in package.json let's go into our source file and add in a debugger statement and see if we can catch this anytime it's called uh when we get this route so let me pull up the log again and let me run a curl oh actually uh you have to enable debugging mode in vs code uh this is f5 or you can go up here and i'm going to run node docker and when you enable debugging you'll get this big orange bar at the bottom so you know that you're in debugging mode so if i now curl our our service then i get a break point so we've officially paused execution at this break point here i can inspect the variables and uh have my watch list over here i can step through things i can continue all the great debugging tools and it's attached to your source file even though it's actually writing as some sort of compiled to javascript version of this so this is an incredibly helpful way to really treat this as if you were developing something directly on your local machine so i'm going to hit continue and there we go the curl command finally finished after 40 seconds uh since i was sitting on the debugger for 40 seconds so there we go we have debugging working in docker uh so that feels pretty good now we have a lot of our node app setup already but let's move on to attaching a database to this thing so in this example we'll use postgres postgres is my go to database for everything and for lots of people so let's add that in here i'm going to go over to my docker compose file and we're going to add another service for postgres and i don't have another docker file for this i'm not going to create one um because postgres and things like postgres and redis and many other different services you actually don't need to define your own docker file or your own repo or project directory or anything like that you can use the pre-built container provided by docker and postgres themselves so i'm going to instead of saying builds the current directory i'm going to use an image that's already available so i'm going to use the official postgres image and if you do a colon then you can specify a version um in that you may not always specify versions for some things especially for local development however for databases you especially want to specify a version because things can be vastly different between different versions of databases in this example i'm going to use postgres 11. i know that's not the quite the latest postgres but i'm planning on doing another video where we deployed this to production as well and the provider that i want to use which is render is currently running on postgres11 so i'm going to match that in preparation for that next video and then i'm also going to use the alpine linux version of this one just to make things super thin light and performant so that's our image i'm also going to define something called restart always here i'm going to one thing you could do this is totally not required but you could also map the default postgres port which is easy to remember it's 5432 you could map that to your local machine if you ever wanted to reach into that postgres running instance we are going to add a way to connect to this via the console later without the need for this so this is just kind of optional if you want to be able to connect to it locally and then finally we're going to set two key environment variables here and i grabbed these from the documentation earlier but in order to let's see one thing we can do is set up our postgres database name so we're going to define our database name here this can be whatever you want so i'm going to say a web app and one thing i'll really like to do is name my database something different in development than production um most people should not be signing on to their production sql console i do sign on to my production sql console sometimes i love sql i love pulling stats and things and it's really helpful for me at that command line to for every query that i execute be able to see which database i'm connected to so i know if i'm connected to something ended in dev then it's safe and i'm fine and then finally uh there's some sort of uh weird uh authentication uh method uh that we need to allow here to trust i don't know honestly what this is off the top of my head but i know that we need this for local development when we're not adding a lot of security passwords and keys and such around this so this kind of opens things up for our local development uh so that defines what we need for postgres next time we do docker compose up if you haven't already i will have on my local machine but if you haven't already it will download this postgres image for you now let's define a bit of configuration for how the web service will connect to this postgres instance so one thing you can define on in docker compose here is this attribute called depends on and i'm going to add on a postgres here and what this does is by default when you run docker compose up it starts all of your services but you can specify to only start a certain service so maybe you have a giant app with lots of different services and you don't need every service every time then i could do like a docker compose up web here and just start my web service but if if the service has it depends on it will also start its dependencies so this is kind of nice it also this also affects um the booting order so the postgres database will boot first because it's a dependency of the web service and that way we don't have any sort of connection issues whenever we're booting our web app so we're we're depending on postgres here the other thing we're going to do is we're going to add in another environment variable called database url this way we can pass in as an environment variable the definition for how our app should connect to the database so that in production we can have our production database url set and here in local development we can have our local database url set so we're going to use the database url syntax here where we can define the the uh type of service host username password database name all in one line so that's uh it looks kind of like a regular url but uh we have postgres uh is the type of database postgres is the uh username postgres is also the host name because in docker compose you automatically have this sort of i guess it is a dns system uh running in the background so that if you call http web it's going to contact the web service or http postgres that's going to point to the postgres service so here we're saying at postgres because that is the name of the host it's the same thing as you know putting in some sort of ip address here this is the name of the host and then finally what is our database name so we want to connect to this specific database so all in one line here that's our database url uh defining how we'll connect to the database using our database library shortly so let me do a docker compose i'm gonna make sure that i don't have any of my test containers from earlier uh do a docker compose uh compose up and now we can see this is going to start booting two containers so we have postgres booting here in the background you'll see lots of log lines the first time postgres boots up um those are fine and then our web service which booted up here so now we have two different services running and we can see those here in our terminal while this is going i want to show before we move on here i want to show off once again the the file restart so if i change this to hello postgres we can see our web container stop and then our web container start again earlier it was a bit harder to see that because uh the logging ended up stopping since that was the only container running but now we have more than one container running you can see just how quick it is really to stop and start a web service again with your new code we've gotten pretty far just a few more steps to prove out this concept and this is looking pretty good so right now what's what we'll do now is set up our app's ability to talk with the database and we'll also set up uh a database migration as well so i'm going to use actually two different packages for this which is might be an unpopular opinion but um the first package i'm going to use is prisma i freaking love prisma now for uh being my database library it has phenomenal uh typescript uh typings uh you can select various columns from your tables include relations and everything you're bringing back in that query is tight it's mind blowing so i really really love prisma as my primary database library prisma also has a migration support it's a preview feature right now called prisma migrate and it's it's great too you'd be fine to check it out and use it just know that it is a preview feature in experimental i'm a database person i really like having more control over it and also having both up and down uh migrations by default the the prism migrate migration service i believe operates off of uh sql files it will generate sql um changes for you in or schema changes for you as sql files uh which is great uh but sometimes for especially not just database like column migrations adding or moving columns and tables and things like that a lot of times it's great to actually script out data migrations so if you are transforming your data from one format to another it's helpful to to dip down into javascript for that as well so for migration's sake i'm actually going to use um next for that now next is also its own whole um i guess you could call orm library it's uh it's a very lightweight one i like it too but we're just going to use the migrations aspect of that so we're going to kind of split our uh roles here so for our database access library we'll use prisma and for a database migrations library we'll use nex k-n-e-x so let's start with prisma so the first thing to do here is do a yarn add actually let me go ahead and i've got a whole bunch of changes here uh we're just gonna mass commit these add eslint prettier postgres docker everything we're just going to commit this in case we uh need to go back and see where it changes again okay let's add prisma yarn add prisma uh it's under the the prisma organizational npm so at prisma cli uh and add that just to dev so prisma works in a very unique way um i haven't seen this in any other npm package in fact they very well very may well be the first to do this what you do is you install the prisma cli the command line interface and then using the command line interface it actually generates a prisma module for you and packs that into the node modules directory and here's why you define a prisma schema file that has your database schema you then use the cli to generate that package so that you get all of those very custom typescript types for you it's very powerful it i'm sure it's very uh complex behind the scenes but they make it simple to use for us so we've installed the cli now let's do an mpx prisma init let's see what happens here make this a little bigger um so we've run prismanit here i'm glad i committed that code earlier because now we can see what has changed so we have four changes within our project first we have a dot m file now if i take a look at this the dot m file defines for us that we need a database url and you may recognize this database url format here we don't need this file because we're running everything in docker compose and that's how we're defining the database url so i'm going to uh delete this file it has then add or we've we've added the prismacli to package.json it's updated yarn.log but really here's the name of the game here is our npx prisma init command also added this schema.prisma file and if you've ever worked with graphql this is very similar to a graphql schema where we're going to define in this custom custom dsl this custom format what our database schema is going to be as far as types go now i will say this is not as explicit and not as specific as our real database types so we'll define things that are strings but we won't give them lengths things like that so it's uh it's you know it's a rough version of uh types it's what it's the types that we need for development in javascript and typescript so because this is not really a database video uh we just want to get this working i'm going to copy in um a schema that i have prepared already so here in our prisma schema file we have this post model so this will end up as a table called posts in our database uh we're gonna have an id slug title content a boolean to say whether or not it's published and created at and updated at time stamps there are various decorators here to tell prisma what these various things should be for instance this one is an id column which makes it the primary key the slug is going to be unique we have a default value unpublished and created at things like this so i'm not going to go over this in depth i highly recommend to look at the prisma documentation for this if you're interested that this is what we need in order to define our prisma schema so i'm going to save that here and then in order to generate that local prisma client what you have to do is you have to run an npx prisma generate and this will now this is the the command line interface that prisma provides and it's generating our database client and putting that in our node modules so we can see here what has happened is it's actually giving us some hints on how we can now go use this in our app so i haven't created any database tables yet all i've defined is just my models for how theoretically things should be so i'm going to copy this into my main source file here this is not going to be hugely organized uh we're just going to mock this out here so i've added in my prismaclient and i just want to show you here i'm going to call this db i like calling these tv i just want to show you here if i do db.post this is really where those typescript and prisma types get very powerful is when i want to go query posts i can say find many posts where and it's going to complete on all of the columns that are relevant for this typing so i could say go find all the posts where published is true and this is going to find all those and and i have types here so if i put this into a post variable if i await that which won't work at top level so i'll add that in here now if i look at the type of this the type of this is post which itself is uh going to have uh if i if i pull the first one i'm gonna do post.map which itself is going to have all of the columns and all of the types on this so this is very powerful prisma adds really excellent way to robustly query for your data and uh do all sorts of things so one of the reasons why i'm a big prisma fan now the caveat to that is uh let me just close this without saving the caveat to that is that because we have to run that prisma generate step we need to do that in our build phase of the docker container as well so i'm going to go back up to our docker file and i'm going to add a step here after our yarn install and similar to kind of the technique we used here for our npm dependencies i'm gonna copy and just our prisma christmas christmas uh i'm just gonna i'm gonna copy and just our schema file here so that is that has been added within a prisma directory so if i want to copy in uh prisma schema.prisma into our prisma directory that it would have ended up in anyway and then i want to run that same command that i ran here locally which is mpx prisma generate and that way by the time our code gets copied in and then to the build phase we do in fact have that prisma client built and available for us locally so that's good one more thing here too is that i want to be sure and uh or one one nice thing that is available is there is a prisma extension wouldn't you know it for vs code uh which helps with things like formatting this file every time you hit save it'll put it in the prisma format and help you with auto auto completions and things like that so i'm going to also add this prisma extension to our growing list of and this might be the last one i think this is the last one our growing list of recommended extensions so that's it for prisma we're not trying it out yet um because i want to get the actual database tables in and then we'll get into querying the data checking out making sure it's all working now let's move on to uh one of the final steps this may be the final one before final test our pre-final step semi-final database migrations like i said i really like using necks for this they have a great database migrations api it also works well with typescript it's defined in typescript javascript so i can easily script things if i need to manipulate data that i'm pushing in and out of the database overall it's just really really nice so i'm going to add in those two packages here i'll do yarn add next and next works with many different databases so you have to install the package specific to the one you want to use which for us is postgres which is the pg package so we'll add in uh next and pg here the next thing you can do is um you can do this in one of two ways so we could add we we need to initialize next and create a configuration file now they have a helper utility here that you can run called next init and because we're in typescript lan i want to tell it to use typescript everywhere even for a configuration file here so this little help for this little helper creates this next file that you can use to configure and you can see with this that you can have a configuration for production for staging for development for all sorts of things you can define a username and password in here you can connect to a sqlite file you can change your pool size you can really do all sorts of configuration we're going to do none of that and just stick really simple here so we're going to just export one object and it's going to be the same no matter what the environment is so we're going to say our client is pg that's postgres our connection we're going to get from what we did earlier we're going to get it from this database url that we're passing in from docker compose and then a production that we might be passing in from whatever our production environment is running so just like other places in javascript we'll get this because this is a typescript configuration file we can get this using javascript so we're going to grab that from our database url and then just for convenience we can also say that on our migrations we want to use the extension type script and that way anytime we generate a migration then that will create a typescript file for us instead of javascript so that is the configuration we need for next we've added the package and we've added this config file now let's write our migration file to get a database table going that will match what we need to query our posts data so next offers some nice little command line utilities here to generate migrations so you can run a next migrate make and then pass it a name for um for your migration so we'll do init db is our name and when we do that it will automatically force create this migrations folder and then by timestamp uh add in migrations here and you can see very similar to the rails format we have up and down migrations here now again because this is not really a database specific video i'm going to copy this in from some code i've prepared here and we'll step through it very quickly so what we have here is we're going to use next to create a table called posts then on that table we're going to add several different columns here the first thing we're going to add is an id column now most tutorials and i'm sure many different companies as well will use auto incrementing integer based ids for their ids i've come to really like using string based ids and a random string generator i like the package nano id nano id to generate my ids so so instead of using otter incrementing integers we're going to use a string here and you can see here within next there is a way to very quickly define a string column but this the string uh function here actually defines a var char which is a varying length string column we're going to have a defined length string column so it will be specifically 16 characters or whatever you may choose long every single time so i'm going to say we're going to find an id column that's a char column of link 16. it will be our primary id column and i'm going to put my prisma file side by side here so you can really see the parallel we're going to have a slug column we can define a length it's not nullable so we're not allowing nulls uh and it's going to be unique so this will add a uniqueness uh constraint there i i just learned this not too long ago there's there a different thing between uniqueness constraint and a unique index um i'd have to look up the docs on this but only i believe this will create a unique constraint let's see then we'll add a title i'll add a text column for content a boolean column for published it's not nullable and then we can default it to a value we'll default it here at false now normally what i'd actually do is i'd create a published at column and make it a date time and then if that's present that means that it's published if it's null that means it's not but we'll keep it a boolean for simplicity here then we'll add a timestamp column for created ad it's not nullable we'll default it to whatever the current now is when a record's created and then an updated ad column then for a down migration so this is if we ever need to roll a migration back the way to reverse our create table is to drop that table so that's what we'll do here and you'll see that all of these columns uh really match what we see in the prisma schema as well so we've defined our migration we have uh we have this going so now let's run it so we need to do a couple of different things here first we've we've added several dependencies lately we've added prisma we've updated our docker file we have added an x so that means anytime you add a dependency that means you need to rebuild your docker container so we're going to do this by hand first but then we're going to go in a bit later and add in a handy little script to do this because you'll find yourself doing this all the time so first we're going to do a docker compose build web so that will rebuild our web service based upon this updated docker file we have that is also generating our prisma client so that will go in fetch the dependencies things like that fetching batching patching a little slower than normal that's abnormally slow i might start that over i'll start it over okay we will rebuild our web container [Music] okay we'll just be patient let it fetch its packages perhaps i killed it too early it's been just running so fast today check a few things while i'm at it here so uh again let's recap so what we're doing is we are rebuilding our container because we have oh good it's working we're rebuilding our container because we've added several dependencies so in docker compose there are a few different steps to do this like i said we're going to we're going to make a short little script or command here that we can run to make that easier but we're first going to rebuild it then we're going to remove the currently running container and then we're going to recreate a new web container again don't worry too much about remembering that because we'll add a script now i will say this there is a lot to remember here and that's partially one of the reasons why i've made this video and uh the blog posts along with this you could you could end up memorizing some of this or much of it but do not in any way feel bad if you can't memorize all this i certainly can't either i've got some uh notes that i've been working on for several days now in order to coalesce all the different things that i've been putting into my node environments here so just have your references handy google the documentation i hope this video and the blog post help you because this this stuff is this stuff is hard to remember it's and a lot of this you only do once at the very beginning of a project and then maybe infrequently for maintenance along the way so this container is going to take a while to build apparently uh what do we have left so we're getting close to the end here what we're going to do is we're going to run this migration and we're going to run this in in an interesting fashion we're not you uh you could run this locally um that's interesting okay so looks like we might have a ch looks like we might have a bug in our code here let me see it failed at this line here copy prisma schema.pris oh i misspelled it primza there we go let's rebuild now if we're lucky yes so for uh we're not just lucky this is how it works like i said every like i said the beginning every line of this is cache so even though it failed at a step it was able to cache all the steps before so we don't have to wait that long again excellent so we've rebuilt our container um now we need to let me check my notes here okay now we need to uh we need to remove the currently running container so we're going to remove and force that removal since it's running and then we want to recreate it so i'm going to run docker compose here darken bows up but uh i'm going to run it with a slash d which is a detached state so it's going to start the containers but run them in the background but here in the other pane we already have our docker compose log going so this is a hand this is just a handy way to start the container um and just get right back to my command line because i have the log going here so we're we're not attaching the log to this terminal over here i already have it ringing over here i hope that makes sense okay we've rebuilt our container um now let's run our migration and see if this works and then we'll create a few little handy shortcuts for us then we'll test this out in our server and call it a day okay let's run our migrations so because i need access to the database and because i need access to all the dependencies i have installed i'm going to run the migration from inside the web container so i'm going to run i'm going to do a docker compose and there are two options here you can either do a docker compose exec exec will execute a command on a currently running container or you could do a docker compose run which will boot up like a temporary instance of that container even if you don't have your docker compose containers running uh and do whatever operation you need i'm gonna i think i'll use run in this case here so we'll do dr most run and we'll run on the web container uh then we're gonna what we're going to run is npx next migrate latest it's a lot huh so what that will do is that will migrate to the latest state that we have in next and it says one ran uh do we trust it i don't know let's go see um so what i'm gonna do at this point is we've done several things here that's a lot of typing on the terminal let's add in some helper scripts that are commonly used that will really help us in development here so one of those things i'm going to add is a script i like to call dv console i was a rails developer uh many a year ago and all of those rails uh command line tools like rails db console and rails db migrator and burned in my head so i kind of like recreating those here in javascript land too so i'm going to make a yarn db console command that can connect me really fast to a database console so i'm going to docker compose um i'm going to do exec here and run it in the currently running postgres container and then use the p sql command line utility to connect to the local instance with the postgres user to the database webapp.dev now that that's a ton to remember and you never want to type that all the time so by saving this we can just simply do yarn db console and now are connected to our database console so let's do a backslash d and that will describe for us all of our current tables or relations so we can see that we have quite a few next tables or actually two next tables and two sequences that's what's used for ids and postgres we have two next tables that keep track of all of the migrations state of which migrations would be has been ran it even has a locking mechanism so that you don't have uh two different instances running migrations against the same database things like that in fact let me just select from that and you can see that it has stored that we have in fact run that one migration that we have then we have our post table so we now have that post table that we defined earlier with all of our columns all of our types and things like that so that is awesome that is great looks like the migration ran fine so this db console script is really helpful another script i like to make is db migrate that's a helpful way to run migrations now in this one what i'm going to do is i'm just going to simply say yarn migrate latest so much kind of like uh yarn start yarn tv migrate is meant to be the production version of migrate so if i were to log on to an instance of my app in production and i wanted to run database migrations i would run yarndb migrate now locally i need those to run inside a docker so i'm going to create a separate one called yarn docker db migrate to specify that this one's going to run inside of docker so again we'll do our docker compose um i think i'll do run here run it on the web container and then i'll just run this command from up above so i'll do yarn db migrate so that is a helpful way for us locally if i quit out of postgres here i can run this safely because it won't let you do the same thing twice so if i do yarn docker db migrate then from inside the web container it's now going to run our migrations which we have none that haven't been ran yet there's another one that's helpful which is i'm gonna copy this yarn db migrate undo so whenever i'm writing migrations i really like testing the up and down version over and over and so uh i'm gonna do dark and pose run web npx migrate down and if you check the docs on next migrate down um oh no i want npx next migrate down if you check the docs on this then this is this will only roll back a single uh migration at a time and then finally to do all that uh do all that uh pump and circumstance around rebuilding your docker containers we're gonna make a really helpful tool to rebuild those quickly so i like creating scripts for rebuild say our web service and this will run those three commands that we ran earlier to rebuild our container so first we'll run a docker compose build web so that'll build our web service and then we want to run a docker compose rm rf web to remove the currently running one and then we want to do a docker compose up slash d for detached to restart that service so uh i don't i don't really need to right now but i'm going to check just to make sure that that is working as well so i'll do a yarn rebuild web so that will go through here and rebuild our web container i'm just gonna let that go in the background uh while we wrap this up so in our final uh foray here what i want to do is actually connect our server or our node server to the database fetch data and show that the two containers postgres and node can talk to each other and communicate so let's open up our let's open up our source file again and we're going to use our prismaclient to connect to the database and return some data now we don't have any data in our database yet so i'm actually going to also create here just a really simple function that checks the database if it has no data shove in a few records for us just so we can have something to play with so let me uh similar to earlier i'm going to create a variable here called db for database and i'm going to say new prismacline this one which has auto imported for me up here and they have a helpful option in here called log and you can specify what all you want to log to the console now in this case i just i would like to log everything so that especially in development we can see everything that's happening here so that's our client then what i want to create is a function to seed some data so i'm going to create a const seed data function here we'll make this an async function because we're going to use some promises here and we're going to check to see if the database post table count is zero so if there's no data in this database then let's do something about that and just add a few dummy records here to get something going so we will um i'm going to add two things so i'm going to wrap this in a promise dot all i'm going to say d uh db post create we're going to create two different posts here so if i if i control space i can see the options here prisma allows me to specify my data and then the select option so the return value of this will actually be the record itself and i could use select to narrow down what fields i want to see so i'm going to do data and then again i can see all of the different columns i can even see the ones that are required the ones that don't have question marks or the ones that are optional the ones that do have question marks so we'll just fill in uh id slug and title for now now ids remember i told you that we're using string ids i just really have come to like those so i'm going to make a function called gen id that will generate an id for us uh and i'll do that here in just a moment but first let's keep going here let's just uh let's create a blog let's create a post for this project so ultimate dev stack and we'll call it the ultimate no dev stack and then let's create another post we'll say some sort of future blog post and same thing here so we've got our seed function yet and uh we'll go ahead and run it on every server run and it'll just if it if the post table does have records it won't add these if it doesn't it will but we do need this gen id column so how do we generate an id well there's this really awesome package i think i've mentioned it already called nano id which is a great uh way to generate a random string of characters that's url safe that's fast the library's small that works uh it works well in urls i said that but this is a great little library for that so i'm going to install that here so yarn looks like something failed here so yarn add nano id and we will generate a function called gen id which we've calling below that will call out to nano id and we want we just want to specify the length so we specified that our id column is 16 characters long so we'll specify a 16 character id here so if i save this what should happen is our web container will reboot i see an error here and i'm betting that's because we don't have can't find the module nano id so let's use our handy new yarn rebuild web command to rebuild our web container now that we have yet another new dependency so we will sit here and wait for it to fetch its packages and build those um while we're at it let's go ahead and uh so we've seeded our database but let's test out returning some data so on our test a root level route here let's return dv post find many we'll just find all of them we could uh we could go here and add conditions and various other options but we're just going to return everything for our test so we're rebuilding our web container because we've added nano id and then we'll test it out and i think we'll call that a day if you've gotten this far i really appreciate you watching along um i hope you found this helpful give it a like if this is something you're into that way i know um what people like on this channel and i'll keep creating more videos like this like i said this is this is everything you really need locally to run this but what about in production too one of my goals after this is to create a video and some material on how to now take this setup into production and run it there and have a very similar setup and configuration between your development and production environments so i'm looking forward to that one so almost done building here and then we can test this out and see if node is communicating with the database i have noticed i think perhaps since we added the prisma package that our build might have slowed down here it was pretty fast before that's okay prism is worth it do do oh i will note if you watch my video on running docker on a raspberry pi i had a ton of fun with that and i did that because i have this new apple m1 chip in my new mac um and docker for mac wasn't compatible with the m1 chip they do now have a preview version of docker for mac that you can run on the m1 chip and that's what i'm using here and it's working great i i don't think i've had any problems with it so far so i'm really happy to see that going so if you're using if you have a new apple laptop with m1 chip then definitely check that out if it hasn't already hit a stable by the time you're watching this there is a preview release for that and you can google it um i also link to it in the blog post at the very top here uh click here for apple m1 chips so you can download the preview release there still building packages over here in dockerland this is something you have to go through if you move over to docker development it might seem i mean it definitely is a downside and it might seem uh just past the level of annoying that you're willing to tolerate however if you think about the number of times you're adding dependencies it's not every single day uh it's not every few minutes like we're doing in this tutorial getting set up so you do have to do it but it's not too too often to be really that annoying and the benefits of using docker i would say far outweigh having to wait here every once in a while for building new dependency packages so just use it to take a break or go get a coffee or something still going here this does seem pretty long do i quit what if it's not working that is interesting it it was going really fast at the beginning of course i had very few dependencies i do think it did slow down when right around when we added prismar next i'm guessing it's prisma one interesting prisma is prism is a very interesting package it you know i talked a bit about earlier how it works where it compiles a client on the fly based on your schema but prisma itself the core of it is actually written in rust and so the prisma has some rust components to it and then it has a wrapper that communicates with those rust components behind the scenes it has a number of moving parts in it um yeah so it's pretty interesting but it's i've been using it now in uh our product we're creating called baton use baton.com and i added it in i don't exactly remember when i think it was it was uh almost a year ago perhaps and or six nine months ago and it has been great for database access it really really has at what point do i stop this and restart it that seems pretty slow it is not normally that slow and check my activity monitor you know what i am going to do i'm going to let's see if we could do a little sleuthing here i'm gonna do a docker ps and this is gonna pull up all the processes i have uh currently running in docker and it looks like i have my postgres container running and then i have this container which is currently building whatever is going on over here so i think on the fly can we do a darker exec because i want to run it in whatever is currently running i'm gonna run a shell uh i might have to do interactive uh haha okay i'm in let's run an h-top oh i wanted to see what was running in this container i do see that this command is running or that's how it started uh there is no h-top well i don't know how to inspect things if there's not an h-top i'm sure there's a way uh this seems it's been running for eight minutes that seems like a super super long time i do think that i'm going to kill this and restart it oops yeah this is running for 10 minutes that's that's entirely too long for this let's try that again what h top versus on top i've never used top huh okay so we're once again building packages here there we go okay moving along not sure what happened earlier so now we're regenerating our prisma client that's good generated copying in all of our source files building our application you can see building it took less than a second uh and then something happened at the bottom our moving stock containers okay so let's run let's restart our docker compose up see if this gets going uh it looks like it had trouble removing [Music] our web container for some reason uh let's run this on our own let me open up our package dot json file um i might not have wanted to do let's see oh yeah this is fs uh rmrf just a uh habit i guess okay so we need to i had the wrong removal command there so we will remove our previous running web container run the new one we can see that this is working now because i'm getting all the prisma logging going and we can see that it has also inserted two records uh into our database so the final moment let's curl oh all right let's see hold on save this no save that uh i didn't actually earlier save my changes to this so let me save this that will restart the web container we don't rebuild anything we just change source um so let's curl our local host port 5000 and we get a bunch of json i'm going to pipe this into a tool called jq which is a nice way to view json you can brew install jq if you're on a mac so here we go this is the data that prisma is fetching from our database both node and postgres are running in docker and everything is working excellent well thank you for staying with me we have done a ton in this but this is now a full node type typescript database postgres eslint prettier debugging stack that you can use to build your next app or maybe integrate some of this into an existing app that you have i hope it was helpful i hope you liked it leave me a like if you liked it or a comment if you have any questions or feedback like i said what i want to do now is create a video where we're taking this and also pushing it into production as well so let me know if that's something you would like to see again there is a full blog post with every single detail every single line of code every single command and explanation uh linked to in the description of this video so check that out as well as a github repository i hope you've had a good time i certainly have have a great day and i'll see you next time
Info
Channel: Kevin Wade
Views: 3,622
Rating: undefined out of 5
Keywords: docker, javascript, nodejs, coding, typescript
Id: AM7HLjUB7lw
Channel Id: undefined
Length: 128min 1sec (7681 seconds)
Published: Tue Dec 29 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.