为什么 dotenv 没有加载到 docker 但在主机上工作正常?

Why dotenv is not loaded in docker but works fine in host machine?

我想构建一个 Docker 映像,它将 运行 我的 node.js 应用程序。我正在使用 dotenv npm 包来存储环境变量。 .env 位于项目的根目录中。当我 运行 我的 npm 脚本从主机启动应用程序 (npm run start_in_docker) 时,一切正常。但是,当我 运行 Docker 容器时,出现以下错误:

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) 

这是我的Docker文件:

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

这是我的 docker-compose.yml 文件,运行 是上面的 Docker 文件:

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

这是我的 package.json 脚本部分:

"scripts": {
    "start_in_docker": "NODE_ENV=development DEBUG=server:*,classes:*,middleware,utils node src/server/main.js",
}

这就是我在 main.js 文件中要求 dotenv 的方式:

require('dotenv').config();

我尝试在 ('dotenv').config() 中指定绝对路径,但没有成功。奇怪的是,如果我 运行 容器 shell (docker run -it myimage /bin/ash) 然后 运行 npm run start_in_docker 它也会起作用。 dotenv 当然在我的 package.json 里。

我认为这是由于:

volumes:
  - ".:/usr/src/app"

在您的 docker-compose 文件中。 link 是应用程序文件夹的当前目录,这意味着包括 node_modules 在内的所有内容都被替换了。

尝试从 docker-compose 中删除卷,看看是否有效。

当您 运行 docker run -it myimage /bin/sh 时,它不会 link 音量,这意味着它将使用正确的 node_modules,这就是为什么它在使用它时有效。