为什么NPM在Docker Container中不可用

Nur*_*ony 10 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"]
Run Code Online (Sandbox Code Playgroud)

我使用以下命令运行容器

docker run -p 8080:8080 -d --name nodejs_expreriments nmrony/exp-nodejs
Run Code Online (Sandbox Code Playgroud)

它运行正常.但是当我尝试浏览时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)
Run Code Online (Sandbox Code Playgroud)

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

Mic*_*lot 11

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

(IMO,如果Dockerfile队会选择这个词BUILD来代替RUNRUN代替的CMD,所以docker build就BUILD陈述和docker run不运行的语句,这可能是对新用户减少混乱.哦,好.)

您要么将前两个CMDs 转换为RUNs(如果您希望它们docker build在图像中发生并被烘焙到图像中),要么将所有三个CMDs转换为您运行的脚本.这里有一些解决方案:

(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
Run Code Online (Sandbox Code Playgroud)

(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
Run Code Online (Sandbox Code Playgroud)

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

(3)如果你经常更改包文件并且不想一直打扰构建和运行,那么另一个选项是有用的,那就是将源保留在卷上的图像之外,这样你就可以运行了没有重建:

...
WORKDIR /src
VOLUME /src
CMD build_and_serve.sh
Run Code Online (Sandbox Code Playgroud)

其中的内容build_and_serve.sh是:

#!/bin/bash
npm install && nodejs server.js
Run Code Online (Sandbox Code Playgroud)

你运行它像:

docker run -v /path/to/your/src:/src -p 8080:8080 -d --name nodejs_expreriments nmrony/exp-nodejs
Run Code Online (Sandbox Code Playgroud)

当然,最后一个选项不会为您提供便携式docker镜像,您可以将某人与您的服务器一起提供给您,因为您的代码位于图像之外的卷上.

很多选择!


pun*_*lly 6

对我来说,这工作:

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
Run Code Online (Sandbox Code Playgroud)

我的debian映像apt-get的npm版本破旧,因此通过下载路径进行了修复。