A
A
Andrey Khokhlov2019-02-11 09:17:34
Node.js
Andrey Khokhlov, 2019-02-11 09:17:34

How do you use Docker and npm/Composer when developing locally (node_modules/vendor folder)?

The task is to install only Git, Docker, the editor you like. Execute `git clone`, `docker-compose up` and start working on the project. A project is any set of services and databases, at least one of which is written in Node.js
Composer tag because the PHP community seems to have the same problem.

Dockerfile
FROM node:10-alpine

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

# Install latest npm
RUN npm i [email protected] -g

WORKDIR /usr/src/app

# Instal dependencies
COPY package*.json ./
RUN npm install

# Copy app code
COPY ./src ./src

# https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md#non-root-user
USER node

CMD ["node", "src/index.js"]

Everything from a million best-practices from the Internet. First, dependencies to cache and not install them each time. Then there are the sources.
docker-compose.yaml
version: '3'

services:
    api:
    environment:
      - NODE_ENV=development
    build:
      context: ./api
      args:
        - NODE_ENV=development
    volumes:
      - ./api:/usr/src/app
      - /usr/src/app/node_modules # mount the node_modules directory to the host machine
    ports:
      - 3000:3000
    command: node_modules/.bin/nodemon src/index.js

Override NODE_ENV, run with nodemon to reload when code changes. And we do the trick with mounting the node_modules folder, without which it is overwritten in the container.
In the end, everything works as it should. You can even either get confused with the rights or just redefine the user in docker-compose.yaml and install new npm packages via `docker-compose exec`.
But there is one "small" problem... On the host, the node_modules folder appears empty. That is, there are no hints in the IDE, there is no way to quickly look into the code of the connected lib, etc.
A few links on the topic with this problem

https://blog.sergeyev.info/docker-development-envi...
https://www.reddit.com/r/docker/comments/915gxp/ma...
https://www.reddit.com/r/docker/comments/6wb2m7/se...
https://stackoverflow.com/questions/38425996/docke...
https://github.com/auxilincom/docker-compose-start...

In the end, I found 2.5 solutions to problem
1. Have Node.js on the machine and install modules on the developer's machine. That is, in the container we have modules for the application to work, and on the host - for autocomplete in the IDE and debugging. The local folder does not conflict with the folder in the container. You can even have the option to run the project with or without docker. It works quickly, there are no performance problems, and most likely the Node.js developer already has a node, and the conditional PHP developer who needs to run the entire project, but does not need to do anything extra to work only with the PHP part.
2. Install dependencies not in the build phase, when we build the container, but at the time of its launch. For example, this can be defined in a script in ENTRYPOINT. And this, in addition to slowing down the launch, is also the synchronization of the bottomless node_modules folder between the host and the container. Google "symphony docker performance", there the role of node_modules is played by the vendor
2.5 folder. Variation 2 options with installing modules on the container to another directory and copying them at startup time.
In my opinion, the solution with duplicating the installation of modules on the local machine looks more adequate in terms of performance and, in general, is a fairly sane compromise.
How are you dealing with this?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
V
Viktor, 2019-02-11
@andrhohlov

For a dev environment, it makes sense to mount all code, including the node_modules folder, as a volume. And do npm i/composer install at the right time.
The same command is executed when building the image, as a result, all the necessary packages are installed during testing and on production.
Yes, this approach leaves the possibility of data discrepancies between dev and prod versions. For my situation, this probability is small enough to be neglected. In another case, you should use your option 2.5.
Options 1 and 2 are not recommended for simple reasons:
1. Violates the principle of uniformity of the environment: if developers, stage, test and prod environments have different versions of nodejs, this can turn into big problems. Therefore, all operations must be performed using programs installed in the container.
2. You can run into a situation where the remote dependency servers do not respond (overloaded, ddos, crashed, etc.) or one of the dependencies is removed from them (I already got it). In other words, the entire contents of the node_modules/vendor folder must be stored in the container. Or let your admin raise a mirror of the same packagist and fool around with the relevance of the packages on it (which makes little sense if you can store everything in a container image).

G
GrungeDev, 2019-02-12
@GrungeDev

In addition to docker, yes docker-compose, in fact, nothing is needed for the dev, because there is already npm / composer inside the container (but this is not accurate) and you can install directly from the container to the mounted volume using "docker-compose run CONTAINER_NAME COMMAND"

G
grinat, 2019-02-13
@grinat

If there are developers on windows, then you need to keep in mind that docker is incompatible with node.js watch, golang fresh, etc., because fs.notify will not work (i.e. nodedemon will not respond to changes). Therefore, in the case of a node, I only throw bases, radishes, etc. into the docker. It is better to throw the database data into external volumes, if it is just into a folder, it will break, postgre is especially sensitive to this. It makes sense to bother with building an image, loading it into the registry if there are a lot of wheelbarrows, otherwise it will be a complete mess, it takes a long time to build, images weigh a hell of a lot, it’s easier to connect through volumes and run composer update, npm i, migrate up in the container, and so that the versions match for a long time lock files were invented, though in php, yes, it will not save, because in packagist the version is not even necessary when creating a package)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question