Nodemon doesn't reload in docker container when files change
Asked Answered
B

5

9

I read many threads sabout this but no one solves anything.

Some say you have to add --legacy-watch (or -L) to the nodemon command. Others shows several different configurations and apparently nodody really knows what you gotta do to achieve server restarting when a file change at the volume inside a docker container.

Here my configuration so far:

Dockerfile:

FROM node:latest

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# install nodemon globally
RUN npm install nodemon -g

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

# Bundle app source
COPY . /usr/src/app

# Exports
EXPOSE 3000

CMD ["npm", "start"]

docker-compose.yml

version: '3.1'

services:
    node:
        build: .
        user: "node"
        volumes:
        - ./:/usr/src/app
        ports: 
            - 3000:3000
        depends_on: 
            - mongo
        working_dir: /usr/src/app
        environment:
        - NODE_ENV=production
        expose:
        - "3000"
    mongo:
        image: mongo
        expose:
        - 27017
        volumes:
        - ./data/db:/data/db
        environment:
            MONGO_INITDB_ROOT_USERNAME: root
            MONGO_INITDB_ROOT_PASSWORD: example

package.json

{
  "name": "node-playground",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon -L"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "ejs": "^2.7.1",
    "express": "^4.17.1",
    "mongoose": "^5.7.1"
  },
  "devDependencies": {
    "nodemon": "^1.19.2"
  }
}

I tried many different setups as well. Like not installing globally nodemon but only as a project dependency. And also running the command at the docker-compse.yml, and i believe many others I don't remember right now. Nothing.

If someone has any cetainty about this, please help. Thanks!!!!

Blink answered 15/9, 2019 at 16:32 Comment(7)
Are you calling nodemon in your NPM script? aka does npm start contain the nodemon command? Can you supply your package.json? I don't see where you are even running the nodemon command...Penoyer
@MattOestreich so sorry, I forgot about that file. Edited.Blink
You run the container as user node, while you also supply a volume that is owned by whatever user owns them in the host system. Are you sure you have the right permissions?Magisterial
So is your container even starting? Is the app inside of your container responsive? Meaning, nodemon starts your app, it just doesn't reload when something changes?Penoyer
@MichałSzydłowski I'll try removing the user reference.Blink
@MattOestreich yes, tha application starts, it just doens't reload at file changes, so you don't see these at the browser.Blink
and which files are changing exactly? You're sure the files that are changing live inside of the container?Penoyer
P
5

I went ahead and created an example container and repo to show how you can achieve this..

Just follow the steps below, which outline how to use nodemon inside of a Docker container.


Docker Container: at DockerHub

Source Code: at GitHub


package.json:

{
  "name": "nodemon-docker-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start:express": "node ./index.js",
    "start": "nodemon"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "nodemon": "^1.19.2"
  }
}

Dockerfile:

FROM node:slim
WORKDIR /app
COPY package*.json ./
RUN apt-get update
RUN npm install
COPY . /app
# -or-
# COPY . .
EXPOSE 1337
CMD ["npm", "start"]

docker-compose.yml: (if you are using it)

version: "3"
services:
  nodemon-test:
    image: oze4/nodemon-docker-test
    ports:
      - "1337:1337"

How to reproduce:

Step 1 USING DOCKER RUN: SKIP IF YOU ARE USING DOCKER COMPOSE (go to step 1 below if you are) pull down example docker container

docker run -d --name "nodemon-test" -p 1337:1337 oze4/nodemon-docker-test

enter image description here


Step 1 USING DOCKER-COMPOSE:

See the docker-compose.yml file above for configuration

  1. cd /path/to/dir/that/has/your/compose/file
  2. docker-compose up -d

enter image description here


Step 2: verify the app works

http://localhost:1337

enter image description here


Step 3: check the container logs, to get a baseline

docker logs nodemon-test

enter image description here


Step 4: I have included a bash script to make editing a file as simple as possible. We need to pop a shell on the container, and run the bash script (change.sh)

  1. docker exec -it nodemon-test /bin/bash

  2. bash change.sh

  3. exit

enter image description here


Step 5: check the logs again to verify changes were made and that nodemon restarted

docker logs nodemon-test

enter image description here



As you can see by the last screenshot, nodemon successfully restarted after changes were made!



Penoyer answered 15/9, 2019 at 20:49 Comment(5)
Uau thanks a lot for your instructions!! i'll tried them when i get back from workBlink
One thought about your example is that I need to achive ths using docker-compose.Blink
@MarcosDiPaolo my bad... I went ahead and added a step that outlines how to accomplish this using docker-compose... I also updated the GitHub Repo with the .yml file... Cheers!!Penoyer
Is it necessary to change the files through docker exec ? Or can you normally code it throug VSCode and changes will be reflected?Diphthong
Hi. Tks for the answer @MattOestreich. Can you outline what was the change you made that did it? I was comparing the equation files and what called my attention were the "node:slim" and the "apt-get" in Dockefile. Is any of those commands that made the difference?Omland
E
27

Try it! This worked for me:

Via the CLI, use either --legacy-watch or -L for short. More informations here.

Exospore answered 24/8, 2020 at 19:59 Comment(3)
Holy sh*t... my code was right! And I was just missing that flag.Diphthong
Other packages have similar flags, for example npmjs.com/package/livereload has the "--usepolling" to activate this behavior. The underlying implementation that uses these flags is npmjs.com/package/chokidarAntivenin
Firstly thanks, it worked for me, but it's too slow and the host doesn't reload the web tab itself, i have to do it manually. Is this a normal behavior, new in docker.Pitiless
P
5

I went ahead and created an example container and repo to show how you can achieve this..

Just follow the steps below, which outline how to use nodemon inside of a Docker container.


Docker Container: at DockerHub

Source Code: at GitHub


package.json:

{
  "name": "nodemon-docker-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start:express": "node ./index.js",
    "start": "nodemon"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "nodemon": "^1.19.2"
  }
}

Dockerfile:

FROM node:slim
WORKDIR /app
COPY package*.json ./
RUN apt-get update
RUN npm install
COPY . /app
# -or-
# COPY . .
EXPOSE 1337
CMD ["npm", "start"]

docker-compose.yml: (if you are using it)

version: "3"
services:
  nodemon-test:
    image: oze4/nodemon-docker-test
    ports:
      - "1337:1337"

How to reproduce:

Step 1 USING DOCKER RUN: SKIP IF YOU ARE USING DOCKER COMPOSE (go to step 1 below if you are) pull down example docker container

docker run -d --name "nodemon-test" -p 1337:1337 oze4/nodemon-docker-test

enter image description here


Step 1 USING DOCKER-COMPOSE:

See the docker-compose.yml file above for configuration

  1. cd /path/to/dir/that/has/your/compose/file
  2. docker-compose up -d

enter image description here


Step 2: verify the app works

http://localhost:1337

enter image description here


Step 3: check the container logs, to get a baseline

docker logs nodemon-test

enter image description here


Step 4: I have included a bash script to make editing a file as simple as possible. We need to pop a shell on the container, and run the bash script (change.sh)

  1. docker exec -it nodemon-test /bin/bash

  2. bash change.sh

  3. exit

enter image description here


Step 5: check the logs again to verify changes were made and that nodemon restarted

docker logs nodemon-test

enter image description here



As you can see by the last screenshot, nodemon successfully restarted after changes were made!



Penoyer answered 15/9, 2019 at 20:49 Comment(5)
Uau thanks a lot for your instructions!! i'll tried them when i get back from workBlink
One thought about your example is that I need to achive ths using docker-compose.Blink
@MarcosDiPaolo my bad... I went ahead and added a step that outlines how to accomplish this using docker-compose... I also updated the GitHub Repo with the .yml file... Cheers!!Penoyer
Is it necessary to change the files through docker exec ? Or can you normally code it throug VSCode and changes will be reflected?Diphthong
Hi. Tks for the answer @MattOestreich. Can you outline what was the change you made that did it? I was comparing the equation files and what called my attention were the "node:slim" and the "apt-get" in Dockefile. Is any of those commands that made the difference?Omland
B
4

All right Thanks a lot to MattOestreich for your answer.
Now i got it working, I don't know what it was, i did follow your set up but of course i'm using docker-compose and i also stripped some things out of it. I'm also not calling mongo image anymore since i setup the db in an Mongodb atlas cluster. my actual config: Dockerfile:

FROM node:12.10

WORKDIR /app

COPY package*.json ./

RUN apt-get update

RUN npm install

COPY . /app

EXPOSE 3000

CMD ["npm", "start"]

docker-compse.yml

version: '3.1'

services:
    node:
        build: .
        volumes:
        - ./:/app
        ports: 
            - 3000:3000
        working_dir: /app
        expose:
        - "3000"

package.json

{
  "name": "node-playground",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "dotenv": "^8.1.0",
    "ejs": "^2.7.1",
    "express": "^4.17.1",
    "mongoose": "^5.7.1"
  },
  "devDependencies": {
    "nodemon": "^1.19.2"
  }
}

thanks Matt again and i hope this thread helps people in need like me.

Blink answered 16/9, 2019 at 22:17 Comment(0)
G
4

Nodemon depends on Chokidar and a potential solution is to make it use polling by setting CHOKIDAR_USEPOLLING environment variable to true.

For example you can do this in docker-compose.yml:

services: 
    api1:
        build: 
            context: .
            dockerfile: Dockerfile
        volumes:
            - /app/node_modules
            - ${PWD}:/app
        ports:
            - 80:3000
        environment:
            - CHOKIDAR_USEPOLLING=true
Glider answered 24/5, 2021 at 13:42 Comment(0)
J
3

Change in Docker file

CMD ["npm", "start"]

Change start script

"start": "nodemon -L server.js"

Build Command

docker build . -t <containername>

Use this command to run the docker container

docker run -v $(pwd):/app -p 8080:8080 -it <container Id>
  • -v = Volumes . the preferred mechanism for persisting data generated by and used by Docker containers.
  • /app = WORKDIR /app
  • $(pwd) = PWD is a variable set to the present working directory. So $(pwd) gets the value of the present working directory
Jun answered 14/10, 2021 at 17:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.