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:
Related
My node application works on my local(MacOS), but it does not work if I use docker.
it works if I try local:
npm install
npm start
It throws error if I try docker
docker-compose build
docker-compose up
I'm getting this error.
Error: Cannot find module '/src/node_modules/sqlite3/lib/binding/napi-v6-linux-musl-x64/node_sqlite3.node'
Package.json
{
"name": "api",
"version": "1.0.0",
"description": "API",
"main": "index.js",
"scripts": {
"test": "rm -rf usersdb.sqlite && jest --forceExit",
"test:coverage": "npm run test -- --coverage --forceExit",
"start": "nodemon app.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.20.1",
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"lodash": "^4.17.21",
"mysql": "^2.18.1",
"nodemon": "^2.0.20",
"sqlite3": "^5.1.4"
},
"devDependencies": {
"jest": "^28.1.1",
"supertest": "^6.3.3"
}
}
docker-compose.yml
version: "3.7"
services:
api:
image: test/api
build: ./
command: npm start
restart: on-failure
environment:
SERVER_PORT: 3004
TOKEN_KEY: test123
volumes:
- .:/src
ports:
- "3004:3004"
Dockerfile
FROM node:12.22-alpine as base
WORKDIR /src
COPY package*.json ./
EXPOSE 3004
RUN apk add --no-cache python2 g++ make
RUN npm install
FROM base as dev
ENV NODE_ENV=development
RUN npm install -g nodemon
COPY . ./
CMD ["nodemon", "app.js"]
Delete the volumes: block from your docker-compose.yml.
The volumes: block in your docker-compose.yml file is overwriting your entire application with content from your host system. That includes overwriting the Linux-OS node_modules tree with the MacOS version from your host system.
You don't need this volumes: block. The code and node_modules: tree are built into your image. If you need to develop your application, you can install Node on your host system (on MacOS this might be as little as brew install node) and use that for day-to-day development, even if you're planning to eventually use Docker for final deployment or if you have dependencies that run in containers.
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:
I am running a docker container that is containing my backend code as a volume:
docker-compose.yml
version: '3'
services:
auth:
container_name: ${AUTH_CONTAINER}
build: ./modules/auth
working_dir: /usr/app
command: "npm install && npm start"
volumes:
- ../backend/modules/auth:/usr/app
expose:
- 9229
ports:
- 9229:9229
Dockerfile:
FROM node:alpine
WORKDIR /usr/app
COPY entrypoint.sh .
ENTRYPOINT ["sh", "/entrypoint.sh"]
Entrypoint:
#!/usr/bin/env bash
exec "$#"
when I run docker-compose up, the first step is always to run yarn. I get an error saying that I should not use both npm and yarn, because I currently am using npm for the project. Is there a way to have node:alpine only use npm only (I know its installed) and then call npm install when docker-compose up is ran?
EDIT: image of console:
EDIT2: Package.json
{
"name": "auth",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1"
}
}
For anyone that gets to this point- and is wondering why this is happening. Ensure that you run the docker-compose -- build FIRST before running docker-compose up that is the problem I was running into.
Dockerfile
FROM node:14
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY entrypoint.sh /
ENTRYPOINT ["sh", "/entrypoint.sh"]
entrypoint:
exec "$#"
docker-compose:
version: '3'
services:
auth:
container_name: "Auth"
build: "./auth"
working_dir: /usr/app
command: "npm start"
environment:
- NODE_ENV=local
volumes:
- ../backend/modules/auth:/usr/app
expose:
- 9299
ports:
- 9229:9229
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.
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