为什么NPM在Docker Container中不可用

时间:2015-02-20 16:15:05

标签: node.js docker

我是码头工人并且玩它的新手。我想在docker容器中运行nodejs app。我把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吗?我做错了吗?

2 个答案:

答案 0 :(得分:10)

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

(IMO,如果Dockerfile团队选择了BUILD而不是RUNRUN而不是CMD,那么docker build就会构建语句和docker run执行RUN语句,这可能不会让新用户感到困惑。哦,好吧。)

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

(1)最简单的更改可能是使用npm install而不是RUN,并使npm install成为#Copy the sources to Container COPY ./src /src WORKDIR /src RUN npm install CMD nodejs server.js 命令。如果您希望在构建期间#Copy the sources to Container WORKDIR /src COPY ./src/package.json /src/package.json RUN npm install COPY /src /src CMD nodejs server.js 能够在运行时快速启动服务器,那么您将会这样做:

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

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

build_and_serve.sh

因此,如果package.json发生更改,您只需要执行npm安装。否则,每次图像中的任何更改时,您都会重建所有内容

(3)如果您经常更改包文件并且不想一直打扰构建和运行,另一个选项很有用,就是保留您的源代码卷上图像的外部,以便您可以在不重建的情况下运行:

#!/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 的内容是:

{{1}}

你运行它:

{{1}}

当然,最后一个选项并没有为您提供便携式泊坞窗映像,您可以将某人与您的服务器一起提供,因为您的代码图像上,在卷上。

很多选择!

答案 1 :(得分:5)

对我来说这很有效:

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正在获取npm的旧版本/旧版本,因此通过下载路径修复了它。