Search code examples
node.jsdockerdocker-composenode-modulesdocker-swarm

Syncing local code inside docker container without having container service running


I have created a docker image which has an executable node js app.

I have multiple modules which are independent of themselves. These modules are created as a package inside docker using npm link command hence can be required in my node js index file.

The directory structure is as

|-node_modules
|-src
  |-app
    |-index.js
  |-independent_modules
    |-some_independent_task
    |-some_other_independent_task

While building the image I have created npm link for every independent module in the root node_modules. This creates a node_modules folder inside every independent module, which is not present in local. This is only created inside the container.

I require these modules in src/app/index.js and proceed with my task.

This docker image does not use a server to keep the container running, hence the container stops when the process ends.

I build the image using

docker build -t demoapp

To run the index.js in the dev environment I need to mount the local src directory to docker src directory to reflect the changes without rebuilding the image.

For mounting and running I use the command

docker run -v $(pwd)/src:/src demoapp node src/index.js

The problem here is, in local, there is no dependencies installed i.e no node_modules folder is present. Hence while mounting local directory into docker, it replaces it with an empty one, hence the dependencies installed inside docker in node_modules vanish out.

I tried using .dockerignore to not mount the node_modules folder but it didn't work. Also, keeping empty node_modules in local also doesn't work.

I also tried using docker-compose to keep volumes synced and hide out node_modules from it, but I think this only syncs when the docker is running with any server i.e docker container keeps running.

This is the docker-compose.yml I used

# docker-compose.yml

version: "2"

services:

  demoapp_container:
    build: .
    image: demoapp
    volumes:
      - "./src:/src"
      - "/src/independent_modules/some_independent_task/node_modules"
      - "/src/independent_modules/some_other_independent_task/node_modules"
    container_name: demoapp_container
    command: echo 'ready'
    environment:
    - NODE_ENV=development

I read this here that using this it will skip the `node_modules from syncing.

But this also doen't works for me.

I need to execute this index.js every time within a stopped docker container with the local code synced to the docker workdir and skipping the dependencies folder i.e node_modules.

One more thing if it could happen will be somewhat helpful. Every time I do docker-compose up or docker-compose run it prints ready. Can I have something, where I can override the command in docker-compose with the command passed from CLI.

Something like docker-compose run | {some command}.


Solution

  • You've defined a docker-compose file but you're not actually using it. Since you use docker run, this is the command you should try:

    docker run \
        -v $(pwd)/src:/src \
        -v "/src/independent_modules/some_independent_task/node_modules" 
        -v "/src/independent_modules/some_other_independent_task/node_modules"
        demoapp \
        node src/index.js
    

    If you want to use the docker-compose, you should change command to be node src/index.js. Then you can use docker-compose up instead of the whole docker run ....