This is a pretty discussed topic but I have never found a solution.
So as you probably know that when I have a volume in my container and I install my dependencies with a yarn install
in a Dockerfile, Yarn will create a node_modules
folder on my container with root:root
access.
I have two problems with this method (on a local/dev environment):
The node_modules
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...
If the host wants to install a package with yarn add ...
he will have to restart and rebuild the container for the package to be installed.
So I came up with another idea, what if I install the dependencies using CMD
in a Dockerfile (or the command
property of a service in a docker-compose
file). So with this, Docker will share with the host the node_modules
. But here is the main issue, node_modules
has a root:root
permissions access, so if your host's username is named for example mint
and don't have the same uid
& gid
you will need to run root access commands to install/remove a dependencies (for example sudo yarn add ...
).
Here is my current config:
docker-compose.yml
:
version: '3.7'
services:
app:
container_name: 'app_DEV'
build: .
command: sh -c "yarn install && node ./server.js"
volumes:
- ./:/usr/src/app
ports:
- 3000:3000
tty: true
Dockerfile
:
FROM node:12.8.1-alpine
WORKDIR /usr/src/app
COPY . .
package.json
:
{
"dependencies": {
"express": "^4.17.1"
}
}
server.js
:
const app = require('express')();
app.get('/', (req, res) => {
res.send('Hello');
});
app.listen(3000, () => console.log('App is listening on port 3000'));
Then you can try to run docker-compose up
then do a ls -la
and you should see something like that:
-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
As you can see every files/folders have mint:mint
access except node_modules
(mint
is my host's user). And this is the issue with this second solution.
And finally, my question is: is there a better way to do this whole thing?
Generally speaking, I would not recommend this approach since you're host & container might not be able to share the same modules. For example, if someone else on your team uses Windows and you have some compiled modules (i.e. node-sass or bcrypt), sharing those makes either the container or the host not able to use them.
Another solution that comes up frequently is to separate the node_modules installation step in your Dockerfile, and to override the volume mount for this. You will still need to rebuild the Docker image every time you want to add a package, but this (probably) shouldn't happen that often down the road.
Here's the relevant parts of the Dockerfile:
FROM node:12.8.1-alpine WORKDIR /usr/src/app COPY ./package*.json . COPY ./yarn.lock . RUN yarn COPY . . CMD [ "yarn", "start" ]
Then, in your docker-compose file:
version: '3.7' services: app: container_name: 'app_DEV' build: . command: sh -c "yarn install && node ./server.js" volumes: - ./:/usr/src/app - /usr/src/app/node_modules/ ports: - 3000:3000 tty: true
Make sure you include the /usr/src/app/node_modules/
volume AFTER the root mount, as it will override it within the container. Also, the trailing slash in important.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With