Nodemon doesn't reload in docker container when files change - node.js

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!!!!

Try it!
This worked for me:
Via the CLI, use either --legacy-watch or -L for short. More informations here.

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
Step 1 USING DOCKER-COMPOSE:
See the docker-compose.yml file above for configuration
cd /path/to/dir/that/has/your/compose/file
docker-compose up -d
Step 2: verify the app works
http://localhost:1337
Step 3: check the container logs, to get a baseline
docker logs nodemon-test
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)
docker exec -it nodemon-test /bin/bash
bash change.sh
exit
Step 5: check the logs again to verify changes were made and that nodemon restarted
docker logs nodemon-test
As you can see by the last screenshot, nodemon successfully restarted after changes were made!

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.

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

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

Related

Docker container changes not reflected in the web browser

Docker version 20.10.21
I have a react frontend, node backend and mongo database app and I want to use docker volume to share the source code. When I mount the backend, changes are automatically reflected in the container. But these changes are not reflected in the web browser even after clearing browser cache and using an incognito window.
Every time there's a change in the code, I have to restarting the containers but this is not the right way to do.
when I start a shell session on the container and check its content it is updated as seen in the snapshot
but in the web browser even after reload is not updated as seen the the following snapshot
I also added nodemon as dependency in package.json for hot reload as seen below
package.json
"scripts": {
"db:up": "migrate-mongo up",
"start": "nodemon --ignore './tests' index.js",
"test": "jest --watchAll --colors"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.1",
"mongoose": "^5.11.13"
},
"devDependencies": {
"jest": "^26.6.3",
"migrate-mongo": "^8.1.4",
"nodemon": "^2.0.7",
"supertest": "^6.1.3"
},
Dockerfile
FROM node:14.16.0-alpine3.13
RUN addgroup app && adduser -S -G app app
USER app
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3001
CMD ["npm", "start"]
docker-compose.yml
---
services:
web:
build: ./frontend
ports:
- 3000:3000
api:
build: ./backend
ports:
- 3001:3001
environment:
DB_URL: mongodb://db/vidly
volumes:
- ./backend:/app
- /app/node_modules
command: ./docker-entrypoint.sh
db:
image: mongo:4.0-xenial
ports:
- 27017:27017
volumes:
- vidly:/data/db
volumes:
vidly:

docker-compose NPM container keeps restarting

I am trying to create a container that is just running cli scripts. At the moment I do not have the scripts written I'm just trying to get the container started first. The following set up creates the container fine, but it keeps restarting and after spending hours trying to find a solution on line I've not got any closer to a solution:
DockerFile
FROM node:18-alpine
WORKDIR /src
COPY package*.json /
EXPOSE 3000
RUN npm install -g nodemon && npm install
COPY . /
docker-compose.yml
version: '3.8'
services:
calculations-script:
restart: unless-stopped
build:
context: .
dockerfile: DockerFile
command: npm run dev
volumes:
- ./:/src
ports:
- "3000:3000"
package.json
{
"name": "test-nodejs-script",
"version": "1.0.0",
"description": "Test script",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "node index.js"
},
"author": "Testing",
"license": "ISC"
}
You container is restarting because of the restart field in your manifest which is set at unless-stopped. unless-stopped ensure that container is always restarted unless manually stopped.
What you probably want is no or on-failure, docs for more details

Running Nodemon in Docker Container

I'm trying to run Nodemon package in a Docker Network with two services, NodeJs and MongoDB.
When I run the app with npm start, nodemon works: I can connect to localhost:3000 and I have the changes in real time. But as soon as I run npm run docker (docker-compose up --build), I can connect to localhost:3000 but I'm not able to see real-time changes on my application nor console.
docker-compose.yml
version: '3.7'
services:
app:
container_name: NodeJs
build: .
volumes:
- "./app:/usr/src/app/app"
ports:
- 3000:3000
mongo_db:
container_name: MongoDB
image: mongo
volumes:
- mongo_db:/data/db
ports:
- 27017:27017
volumes:
mongo_db:
dockerfile
FROM node:alpine
WORKDIR /app
COPY package.json /.
RUN npm install
COPY . /app
CMD ["npm", "run", "dev"]
package.json
{
"name": "projectvintedapi",
"version": "0.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node index.js",
"dev": "nodemon index.js",
"docker": "docker-compose up --build"
},
"license": "ISC",
"dependencies": {
"dotenv": "^16.0.0",
"express": "^4.17.3",
"mongodb": "^4.5.0",
"nodemon": "^2.0.15"
}
}
docker-compose.yml tells Docker to boot a container, the Node.js application. It also tells Docker to mount a host volume:
volumes:
- "./app:/usr/src/app/app"
As a result, Docker will mount the ./app directory on your laptop, which contains your code, into the container at /usr/src/app/app.
Once you’ve changed your code on your laptop/desktop, nodemon detects that change and restarts the process without rebuilding the container. To make this happen, you need to tell Docker to set the entrypoint to nodemon. Do that in the Dockerfile:
FROM node:alpine
WORKDIR /app
COPY . /app
RUN npm install -g nodemon
RUN npm install
#Give the path of your endpoint
ENTRYPOINT ["nodemon", "/usr/src/app/server.js"]
CMD ["npm", "run", "dev"]
With host volumes and nodemon, your code sync is almost instantaneous.
Fixed it: it was for bind mount
dockerfile
FROM node:16.13.2
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . ./
CMD ["npm", "run", "start"]
docker-compose.yml
version: '3.7'
services:
app:
container_name: NodeJs
build: .
command: npm run dev
volumes:
- .:/app
ports:
- 3000:3000
mongo_db:
container_name: MongoDB
image: mongo
volumes:
- mongo_db:/data/db
ports:
- 27017:27017
volumes:
mongo_db:

Docker Nodemon not reloading on changes even though -L is set

Hi I'm trying to dockerize an app im currently working on. It uses nodejs and mariadb. I have some difficulties with figuring out how to make nodemon work.
I tried using --legacy-watch or -L which is the short form but it didn't change the result.
NPM installs all dependecies correct i even get the nodemon text but it doesn't restart the server when i make changes.
Would be gal if anyone could help
package.json:
{
"name": "nodejs_mariadb_docker_test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node src/index.js",
"dev": "nodemon -L src/index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.2",
"mariadb": "^2.5.5",
"nodemon": "^2.0.15"
}
}
Dockerfile for nodejs:
# Specifies the image of your engine
FROM node:16.13.2
# The working directory inside your container
WORKDIR /app
# Get the package.json first to install dependencies
COPY package.json /app
# This will install those dependencies
RUN npm install
# Copy the rest of the app to the working directory
COPY . /app
# Run the container
CMD ["npm", "run", "dev"]
and the docker compose file:
version: "3"
services:
node:
build: .
container_name: express-api
ports:
- "80:8000"
depends_on:
- mysql
mysql:
image: mariadb:latest
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: "password"
volumes:
- mysqldata:/var/lib/mysql
- ./mysql-dump:/docker-entrypoint-initdb.d
volumes:
mysqldata: {}
So the obvious problem is that you do not mount your code into the container. That is why nodemon cannot see any changes, and react to them.
Additionally, it may be more straight forward to develop the application locally and only use docker as a mean to package/ship it.
If you still want to go down this route, I would suggest something like this.
services:
express-api:
build: ./
# overwrite the prod command
command: npm run dev
ports:
- "80:8000"
volumes:
# mount your code folder into the app folder
- .:/app
# mysql stuff ...
In your dockerfile you can swap the command for the production one, since in development, compose will override it.
FROM node:16.13.2
WORKDIR /app
COPY package.json package-lock.json ./
# use ci to install from the lock file,
# to avoid suprises in prod
RUN npm ci
COPY . ./
# use the prod command
CMD ["npm", "run", "start"]
This will do a bit of redundant work in development, like copying the code, but it should be OK.
Additionally, you may want to use a .dockerignore to ignore the mysqldump for example. Otherwise, it will be copied into the image, which is probably not desirable.
Also note that through npm ci your dependencies are locked, and won't update automatically. It will also throw errors if your lock file is not in sync with package.json. This is what you want for production. If you develop locally, you can run npm install locally or via docker exec to bump the dependencies, if required. Then you can check if nothing is broken, and be sure that for your prod image it will be fine since it's used from the lock file again.

How do you setup Nodemon in a Docker container?

I am trying to setup Nodemon in a Docker container. It says that nodemon is running, but when I change code in my index.js file it does not reload like it does outside of docker. I've tried adding -L to the command, but no luck. I've also tried installing nodemon in the docker file instead, but no luck.
I have to do docker-compose up --build anytime I change my index.js file.
Any ideas?
Here is my file structure:
-api
-node_modules
-.dockerignore
-Dockerfile
-index.js
-package.json
-package-lock.json
-docker-compose.yml
docker-compose.yml:
version: '3.4'
services:
api:
build:
context: ./api
container_name: api
environment:
- PORT=3001
volumes:
- ./api/src:/usr/app/src
ports:
- '3001:3001'
command: npm run dev
Dockerfile:
FROM node:14.15.2-alpine3.12
WORKDIR /usr/app
COPY package*.json ./
RUN npm install
COPY . .
package.json:
{
"name": "api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"express": "^4.17.1"
},
"scripts": {
"dev": "nodemon index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"nodemon": "^2.0.6"
}
}
I FIGURED IT OUT!!!
After a lot of trial and error. It has to do with my volumes in my docker compose as well as nodemon. Not 100% sure why any insight would be helpful too.
The fix was to change my volume from
- ./api/src:/usr/app/src
to:
- ./api:/usr/src/app
Then I had to add the -L flag to my nodemon command in order for it to reload.

Resources