node.js - 为什么 NPM 在 Docker 容器中不可用

标签 node.js docker

我对 docker 非常陌生,并且正在使用它。我正在尝试在 docker 容器中运行 nodejs 应用程序。我将 ubuntu:14.04 作为基础镜像并构建了我自己的 nodeJS 烘焙镜像。我的 Dockerfile 内容如下所示

FROM ubuntu:14.04

MAINTAINER nmrony

#install packages, nodejs and npm
RUN apt-get -y update && \
    apt-get -y install build-essential && \
    curl -sL https://deb.nodesource.com/setup | bash - && \
    apt-get install -y nodejs

#Copy the sources to Container
COPY ./src /src
CMD ["cd /src"]
CMD ["npm install"]

CMD ["nodejs", "/src/server.js"]

我使用以下命令运行容器

docker run -p 8080:8080 -d --name nodejs_expreriments nmrony/exp-nodejs

运行良好。但是当我尝试浏览 http:localhost:8080 时它不会运行。 当我运行 docker logs nodejs_expreriments 时,出现以下错误

Error: Cannot find module 'express'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/src/server.js:1:77)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)

我用交互式 shell 运行另一个容器,发现 npm 没有安装。有人可以帮我为什么 NPM 没有安装在容器上吗?我做错了吗?

最佳答案

您的根本问题是,您只能在 Docker 文件中准确地拥有 一个 CMD。每个 RUN/COPY 命令在 docker build 期间构建一个层,因此您可以拥有任意数量的层。但是,one CMD 会在 docker run 期间执行。由于您有三个 CMD 语句,因此实际上只有一个被执行(大概是最后一个)。

(IMO,如果 Dockerfile 团队会选择单词 BUILD 而不是 RUNRUN 而不是 CMD,因此 docker build 执行 BUILD 语句,而 docker run 执行 RUN 语句,这对新用户来说可能不会那么困惑。哦,好吧。)

您要么希望将前两个 CMD 转换为 RUN(如果您希望它们在 docker build 期间发生并且是烘焙到图像中)或者可能将所有三个 CMD 放在您运行的脚本中。以下是一些解决方案:

(1) 最简单的更改可能是使用 WORKDIR 而不是 cd 并使您的 npm install 成为 RUN命令。如果您希望能够在构建期间 npm install 以便您的服务器在运行时快速启动,您需要这样做:

#Copy the sources to Container
COPY ./src /src
WORKDIR /src
RUN npm install
CMD nodejs server.js

(2) 如果您正在进行主动开发,您可能需要考虑以下内容:

#Copy the sources to Container
WORKDIR /src
COPY ./src/package.json /src/package.json
RUN npm install
COPY /src /src
CMD nodejs server.js

因此,如果您的 package.json 发生更改,您只需执行 npm install。否则,每次图像中的任何东西发生变化时,你都会重建所有东西

(3) 如果您经常更改包文件并且不想一直为构建和运行而烦恼,另一个有用的选项是将源代码卷上的图像,以便您无需重建即可运行:

...
WORKDIR /src
VOLUME /src
CMD build_and_serve.sh

build_and_serve.sh的内容在哪里:

#!/bin/bash
npm install && nodejs server.js

然后你像这样运行它:

docker run -v /path/to/your/src:/src -p 8080:8080 -d --name nodejs_expreriments nmrony/exp-nodejs

当然,最后一个选项不会为您提供可移植的 docker 镜像,您可以将其与您的服务器一起提供给他人,因为您的代码在镜像之外在一个卷上。

很多选择!

关于node.js - 为什么 NPM 在 Docker 容器中不可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28633438/

相关文章:

docker - 将本地视频文件流式传输为 RTSP 并发布到端口

node.js - 仅返回 1 个查找文档,但我请求 3 个 id 来查找 Node/express

javascript - 解决nodejs选项中的变量

javascript - Discord.js - 让用户上次事件?

ubuntu - 通过 Docker 在 EC2 Ubuntu 实例上运行 iPython notebook 服务器

docker - 以非root用户身份运行docker容器进程

docker - 如何在Docker容器中连接本地Kafka?

node.js - 从 Firebase/Google Cloud Storage 读取作为 Node.js 函数中的缓冲区

node.js - 如何在Web上使用Node js和socket io从BW08车辆跟踪器(GPS)获取数据?

docker - 从 Docker 容器获取 Mac 地址