title: Sharing the `node_modules` folder between the container and the host
body: <p>This is a pretty discussed topic but I have never found a solution.</p>
  
  <p>So as you probably know that when I have a volume in my container and I install my dependencies with a <code>yarn install</code> in a Dockerfile, Yarn will create a <code>node_modules</code> folder on my container with <code>root:root</code> access.</p>
  
  <p>I have two problems with this method (on a local/dev environment):</p>
  
  <ol>
  <li><p>The <code>node_modules</code> folder is only in my container, but the host's code editor (mine is VSC) probably need this folder to work properly. For example, if you don't have it, VSC will yell at you that he cannot find the imported modules...</p></li>
  <li><p>If the host wants to install a package with <code>yarn add ...</code> he will have to restart and rebuild the container for the package to be installed.</p></li>
  </ol>
  
  <p>So I came up with another idea, what if I install the dependencies using <code>CMD</code> in a Dockerfile (or the <code>command</code> property of a service in a <code>docker-compose</code> file). So with this, Docker will share with the host the <code>node_modules</code>. But here is the main issue, <code>node_modules</code> has a <code>root:root</code> permissions access, so if your host's username is named for example <code>mint</code> and don't have the same <code>uid</code> &amp; <code>gid</code> you will need to run root access commands to install/remove a dependencies (for example <code>sudo yarn add ...</code>).</p>
  
  <p>Here is my current config:</p>
  
  <p><code>docker-compose.yml</code>:</p>
  
  <pre><code>version: '3.7'
  
  services:
    app:
      container_name: 'app_DEV'
      build: .
      command: sh -c "yarn install &amp;&amp; node ./server.js"
      volumes:
        - ./:/usr/src/app
      ports:
        - 3000:3000
      tty: true
  </code></pre>
  
  <p><code>Dockerfile</code>:</p>
  
  <pre><code>FROM node:12.8.1-alpine
  
  WORKDIR /usr/src/app
  
  COPY . .
  </code></pre>
  
  <p><code>package.json</code>:</p>
  
  <pre><code>{
    "dependencies": {
      "express": "^4.17.1"
    }
  }
  </code></pre>
  
  <p><code>server.js</code>:</p>
  
  <pre class="lang-js prettyprint-override"><code>const app = require('express')();
  
  app.get('/', (req, res) =&gt; {
    res.send('Hello');
  });
  
  app.listen(3000, () =&gt; console.log('App is listening on port 3000'));
  </code></pre>
  
  <p>Then you can try to run <code>docker-compose up</code> then do a <code>ls -la</code> and you should see something like that:</p>
  
  <pre><code>-rw-r--r--  1 mint mint   215 août  23 16:39 docker-compose.yml
  -rw-r--r--  1 mint mint    56 août  23 16:29 Dockerfile
  drwxr-xr-x 52 root root  4096 août  23 16:31 node_modules
  -rw-r--r--  1 mint mint    53 août  23 16:31 package.json
  -rw-r--r--  1 mint mint   160 août  23 16:29 server.js
  </code></pre>
  
  <p>As you can see every files/folders have <code>mint:mint</code> access except <code>node_modules</code> (<code>mint</code> is my host's user). And this is the issue with this second solution.</p>
  
  <p>And finally, my question is: is there a better way to do this whole thing?</p>