为什么 NPM 在 Docker 容器中不可用

Why NPM is not available in Docker Container

我对 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"]

I 运行 容器使用以下命令

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 期间构建一层,因此您可以拥有任意数量的层。但是,在 docker run 期间恰好执行了 one CMD。由于您有三个 CMD 语句,因此实际上只有一个被执行(大概是最后一个)。

(IMO,如果 Docker 文件团队会选择 BUILD 而不是 RUNRUN 而不是 CMD,那么docker build 执行 BUILD 语句,docker 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 安装。否则,每当您的映像中的 任何东西 发生变化时,您都会重建 所有东西

(3) 如果您经常更改包文件并且不想一直被构建和 运行ning 所困扰,另一个有用的选项是保留您的源代码 外部 卷上的映像,这样您就可以 运行 而无需重建:

...
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 图像,您可以通过您的服务器将其提供给其他人,因为您的代码 图像之外, 在卷上。

很多选择!

对我来说这很有效:

RUN apt-get update \
    && apt-get upgrade -y \
    && curl -sL https://deb.nodesource.com/setup_8.x | bash - \
    && apt-get install -y nodejs \
    && npm install -g react-tools

我的 debian 映像 apt-get 正在获取 broken/old 版本的 npm,因此通过下载路径修复了它。