<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Akshay Gupta</title>
    <description>The latest articles on DEV Community by Akshay Gupta (@akshaydotsh).</description>
    <link>https://dev.to/akshaydotsh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F689532%2Fb4471aa5-2100-446e-bedf-8b3d8b07fc29.jpeg</url>
      <title>DEV Community: Akshay Gupta</title>
      <link>https://dev.to/akshaydotsh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akshaydotsh"/>
    <language>en</language>
    <item>
      <title>Docker in development (with Node.js)</title>
      <dc:creator>Akshay Gupta</dc:creator>
      <pubDate>Wed, 15 Sep 2021 13:22:29 +0000</pubDate>
      <link>https://dev.to/akshaydotsh/docker-in-development-with-node-js-454k</link>
      <guid>https://dev.to/akshaydotsh/docker-in-development-with-node-js-454k</guid>
      <description>&lt;p&gt;This post is going to help you find out how to setup docker in such a way that you can easily and quickly get started using docker in development environment with Node.js without much hassle! &lt;/p&gt;

&lt;p&gt;We will be learning basics of &lt;strong&gt;Docker Volumes&lt;/strong&gt; first and then move on to how to use volumes during the development phase!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Volumes are the preferred mechanism for persisting data generated by and used by Docker containers.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Basics Of Volumes
&lt;/h2&gt;

&lt;p&gt;Creating volume is pretty simple using the docker &lt;code&gt;create&lt;/code&gt; command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker volume create myvol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also remove the volume straight away by using the remove command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker volume remove myvol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also verify that the volume has been created by using &lt;code&gt;list&lt;/code&gt; command to list volumes on your system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker volume &lt;span class="nb"&gt;ls
&lt;/span&gt;DRIVER    VOLUME NAME
&lt;span class="nb"&gt;local     &lt;/span&gt;88b0dd3439a42b08ab161dfb718b1fdcb548d776521f0e008a0e6b002ecd1ee7
&lt;span class="nb"&gt;local     &lt;/span&gt;96a6b003a662d7461c100e3bef816322f036adba8eef1483755551aa463ba7b4
&lt;span class="nb"&gt;local     &lt;/span&gt;myvol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see our volume &lt;code&gt;myvol&lt;/code&gt; is created with local driver. We can also go ahead and get some more information regarding the volume with the &lt;em&gt;inspect&lt;/em&gt; command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker inspect myvol
&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"CreatedAt"&lt;/span&gt;: &lt;span class="s2"&gt;"2021-09-13T18:20:00Z"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Driver"&lt;/span&gt;: &lt;span class="s2"&gt;"local"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Labels"&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;,
        &lt;span class="s2"&gt;"Mountpoint"&lt;/span&gt;: &lt;span class="s2"&gt;"/var/lib/docker/volumes/myvol/_data"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Name"&lt;/span&gt;: &lt;span class="s2"&gt;"myvol"&lt;/span&gt;,
        &lt;span class="s2"&gt;"Options"&lt;/span&gt;: &lt;span class="o"&gt;{}&lt;/span&gt;,
        &lt;span class="s2"&gt;"Scope"&lt;/span&gt;: &lt;span class="s2"&gt;"local"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Among other information this command show the Mountpoint for our volume data, which is &lt;code&gt;/var/lib/docker/volumes/myvol/_data&lt;/code&gt;. We can very well &lt;code&gt;cd&lt;/code&gt; into this dir and see the data for the volume. This data could be your codebase, or the metadata or any other data that you store in the volume&lt;/p&gt;

&lt;h3&gt;
  
  
  But there is a catch!!
&lt;/h3&gt;

&lt;p&gt;Are you a mac user ? If you're not a mac user you can skip this section but if you are this might be helpful. You can't directly cd into the /docker folder if you do try to do that it would give&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/lib/docker
&lt;span class="nb"&gt;cd&lt;/span&gt;: no such file or directory: /var/lib/docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why is that ?!&lt;/p&gt;

&lt;p&gt;That is because Docker Desktop (on mac) actually runs a VM behind the scenes because docker, because of the way its made, is not directly compatible with mac. But there are ways to access the underlying data in the VM.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One option is to log into the shell using &lt;code&gt;netcat&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nc &lt;span class="nt"&gt;-U&lt;/span&gt; ~/Library/Containers/com.docker.docker/Data/debug-shell.sock

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then cd into the data directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/ # cd /var/lib/docker/volumes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can exist the shell by typing &lt;code&gt;exit&lt;/code&gt; command or pressing &lt;code&gt;ctrl+c&lt;/code&gt; on keyboard&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Another option is using nsenter in privileged container like below
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--privileged&lt;/span&gt; &lt;span class="nt"&gt;--pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host debian nsenter &lt;span class="nt"&gt;-t&lt;/span&gt; 1 &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will open the shell same way as the first option. &lt;br&gt;
Checkout this &lt;a href="https://gist.github.com/BretFisher/5e1a0c7bcca4c735e716abf62afad389"&gt;gist&lt;/a&gt; by &lt;strong&gt;Bret Fisher&lt;/strong&gt; to know more :)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: For windows users, docker artifacts can be found at &lt;code&gt;\\wsl$\docker-desktop-data\version-pack-data\community\docker\&lt;/code&gt;. If this does not work, I would suggest going through related discussions on stackoverflow and docker forums (example: &lt;a href="https://forums.docker.com/t/volume-mounts-in-windows-does-not-work/10693/22"&gt;here&lt;/a&gt;) to see how to access data&lt;/p&gt;

&lt;p&gt;Cool! Now that we are done with basics of volumes 🎉 Let's jump onto the code!&lt;/p&gt;
&lt;h3&gt;
  
  
  A Node.js Express API
&lt;/h3&gt;

&lt;p&gt;Let's quickly setup an express application. We won't waste much time here we'll pull sample "hello world" example from express.js website&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;node_docker_demo
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;node_docker_demo
&lt;span class="nv"&gt;$ &lt;/span&gt;yarn init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add express
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;index.js&lt;/code&gt; let's paste the following sample code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Example app listening at http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have an express application running .. let's write our Dockerfile!!&lt;/p&gt;

&lt;h3&gt;
  
  
  Dockerfile Setup
&lt;/h3&gt;

&lt;p&gt;We will start with pull &lt;code&gt;node:latest&lt;/code&gt; image from the registry (It doesn't matter the version we pull from registry in our case because it is a simple express app but you might want to stick to a version for backward-compatibility issues or do the node.js and dependencies upgrade accordingly)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's also set our work directory in the image so that we don't have to mention absolute path everytime&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next up, we will install node_modules in our image and for that we would need &lt;code&gt;package.json&lt;/code&gt; and either &lt;code&gt;yarn.lock&lt;/code&gt; or &lt;code&gt;package-lock.json&lt;/code&gt; file (depending on if you used yarn or npm) in the image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ["package.json", "yarn.lock", "./"]&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would copy both package.json and yarn.lock into the current working directory (specified by &lt;code&gt;./&lt;/code&gt;). &lt;br&gt;
Note: our current working directory has been set to &lt;code&gt;/app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Running yarn install after that would install all the required dependencies in node_modules&lt;/p&gt;

&lt;p&gt;Now our directory structure inside the image looks something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app
 |_ package.json
 |_ yarn.lock
 |_ node_modules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next let's copy everything else we have in our project with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will copy everything from our host's current working (&lt;code&gt;.&lt;/code&gt;) dir to image's working dir (&lt;code&gt;.&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;All there's left to do is run the server with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;, &lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All in all our Dockerfile looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:latest&lt;/span&gt;

&lt;span class="c"&gt;# setting work dir&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;## Following steps are done before copying the remaining file&lt;/span&gt;
&lt;span class="c"&gt;## to make use of docker's caching capabilities&lt;/span&gt;
&lt;span class="c"&gt;# copying files required to install node modules&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ["package.json", "yarn.lock", "./"]&lt;/span&gt;

&lt;span class="c"&gt;# install node_modules &lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# copy everything else&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# mention the port which we'll expose with port-mapping &lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="c"&gt;# run server&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;, &lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Gotcha!&lt;/em&gt; There is a small issue here, and that is that we are installing node modules with yarn install before copying every other file but then when we do &lt;code&gt;COPY . .&lt;/code&gt; we would be again copying node_modules into the image. To prevent this we will make a &lt;code&gt;.dockerignore&lt;/code&gt; file and tell docker to ignore node_modules while copying data inside the image&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.dockerignore&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's build this with &lt;code&gt;docker build&lt;/code&gt; command and then run it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; myapp &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:300 &lt;span class="nt"&gt;--name&lt;/span&gt; myapp_container myapp
Example app listening at http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have now successfully containerized our node.js application but there is one issue that we have:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If we make any change in our codebase, as we do hundreds of thousands of times during development, we would need to rebuild the image and run the container again (hundreds of thousands of times)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That can't be a good strategy. There must be a better way to do this.&lt;br&gt;
Thankfully, there is! VOLUMES! 😍&lt;/p&gt;

&lt;p&gt;For the purposes of this use-case we will use &lt;strong&gt;bind mounts&lt;/strong&gt;. Essentially we will bind our host's current working directory to the image's working dir (&lt;code&gt;/app&lt;/code&gt;) and attach a file watcher (e.g. &lt;code&gt;nodemon&lt;/code&gt;) so that as soon as we save a change in development, that change get's propagated to the image (because volume!), so nodemon would detect that change and reload our node.js server&lt;/p&gt;

&lt;p&gt;We can configure bind-mount while running our container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker run -it --rm \
  -p 3000:300 \
  -v $(pwd):/app \
  --name myapp_container \
  myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-v $(pwd):/app&lt;/code&gt; above would mount the current working dir to /app. Another way to do it is using &lt;code&gt;--mount&lt;/code&gt; flag&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker run -it --rm \
  -p 3000:3000 \
  --mount type=bind,source=$(pwd),target=/app \
  --name myapp_container 
  myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is fine and dandy, but it's not enough! We also need to configure a file watcher like we discussed. Along with the file watcher another thing to keep in mind is since we are using bind-mounts now, there is no need to actually &lt;code&gt;COPY&lt;/code&gt; anything from our local host to image !! So let's remove that and add nodemon into our image and see how things look&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:latest&lt;/span&gt;

&lt;span class="c"&gt;# setting work dir&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# added nodemon globally&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; nodemon

&lt;span class="c"&gt;# run the server with watcher&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["nodemon", "index.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it!! Let's build this file and run it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; myapp &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:300 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/app &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; myapp_container &lt;span class="se"&gt;\&lt;/span&gt;
  myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when we make a code change, the watcher will detect it and restart the node.js server automatically!&lt;/p&gt;

&lt;p&gt;And, that is how you can start with developing Node.js applications on docker!&lt;/p&gt;

&lt;p&gt;🥳 🥳 🥳 &lt;/p&gt;

</description>
      <category>docker</category>
      <category>javascript</category>
      <category>node</category>
      <category>container</category>
    </item>
  </channel>
</rss>
