I want to build an Docker image which will run my node.js application. I'm using dotenv npm package to store environment variables. The .env
is located in the root of the project. When I run my npm script which starts the application (npm run start_in_docker
) from host machine everything works perfectly. However when I run Docker container I get the following error:
internal/modules/cjs/loader.js:584
throw err;
^
Error: Cannot find module 'dotenv'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:582:15)
at Function.Module._load (internal/modules/cjs/loader.js:508:25)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)
at Object.<anonymous> (/usr/src/app/src/server/main.js:3:1)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
This is my Dockerfile:
FROM node:10-alpine
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./
RUN apk add --update python
RUN apk add --update vim
RUN apk add --update sqlite
RUN npm install --only=production
# Bundle app source
COPY . .
EXPOSE 3000
RUN npm install --unsafe-perm=true sqlite3 -g
RUN npm install pm2 -g
# run node-gyp to build sqlite3
RUN cd /usr/src/app/node_modules/sqlite3 && npm run install
WORKDIR /usr/src/app
This is my docker-compose.yml file which runs the Dockerfile above:
version: '3'
services:
appstore-bl-server:
container_name: appstore-bl-server-production
build:
dockerfile: Dockerfile-prod
context: .
volumes:
- ".:/usr/src/app"
ports:
- "3000:3000"
networks:
- appstore-net
command: npm run start_in_docker
networks:
appstore-net:
driver: bridge
This is my package.json scripts section:
"scripts": {
"start_in_docker": "NODE_ENV=development DEBUG=server:*,classes:*,middleware,utils node src/server/main.js",
}
and this is how I require dotenv
in my main.js file:
require('dotenv').config();
I tried specifying the absolute path in ('dotenv').config()
but it didn't work. What's strange is that if I run the container shell (docker run -it myimage /bin/ash
) and then run npm run start_in_docker
it will also work. dotenv
is in my package.json of course.
I think this is caused by:
volumes:
- ".:/usr/src/app"
in your docker-compose file. This links the current dir to the app folder, meaning everything including node_modules
is replaced.
Try removing the volumes from docker-compose
and see if it works.
When you run docker run -it myimage /bin/sh
it will not link the volume, meaning it will be using the correct node_modules
, which is why it works when using that.