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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28633438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 18:27:04  来源:igfitidea点击:

Why NPM is not available in Docker Container

node.jsdocker

提问by Nur Rony

I am very new to docker and playing with it. I am trying to run nodejs app in docker container. I took ubuntu:14.04 as base image and build my own nodeJS baked image. My Dockerfilecontent looks like below

我对 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 run container using following command

我使用以下命令运行容器

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

It runs fine. But when I try browse http:localhost:8080it does not run. When I run docker logs nodejs_expreriments, I got the following error

它运行良好。但是当我尝试浏览时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)

I run another container with interactive shell and found that npm is not installed. Can someone help me why NPM is not installed on container? Am I doing something wrong?

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

回答by Mickalot

Your fundamental problem is that you can only have exactly oneCMDin a Docker file. Each RUN/COPYcommand builds up a layer during docker build, so you can have as many of those as you want. However, exactly oneCMDgets executed during a docker run. Since you have three CMDstatements, only one of them actually gets executed (presumably, the last one).

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

(IMO, if the Dockerfile team would have chosen the word BUILDinstead of RUNand RUNinstead of CMD, so that docker builddoes BUILD statements and docker rundoes RUN statements, this might have been less confusing to new users. Oh, well.)

(IMO,如果 Dockerfile 团队选择了这个词BUILD而不是RUNandRUN而不是CMD,那么docker buildBUILD 语句和docker runRUN 语句就这样,这对新用户来说可能不那么令人困惑。哦,好吧。)

You either want to convert your first two CMDs to RUNs (if you expect them to happen during the docker buildand be baked into the image) or perhaps put all three CMDs in a script that you run. Here's a few solutions:

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

(1) The simplest change is probably to use WORKDIRinstead of cdand make your npm installa RUNcommand. If you want to be able to npm installduring building so that your server starts up quickly when you run, you'll want to do:

(1) 最简单的更改可能是使用WORKDIR而不是cd使您npm installRUN命令。如果您希望npm install在构建期间能够在运行时快速启动服务器,您需要执行以下操作:

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

(2) If you're doing active development, you may want to consider something like:

(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

So that you only have to do the npm install if your package.json changes. Otherwise, every time anythingin your image changes, you rebuild everything.

这样您只需在 package.json 更改时执行 npm install 。否则,每次图像中的任何内容发生变化时,您都会重建所有内容

(3) Another option that's useful if you're changing your package file often and don't want to be bothered with both building and running all the time is to keep your source outsideof the image on a volume, so that you can run without rebuilding:

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

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

Where the contents of build_and_serve.share:

其中的内容build_and_serve.sh是:

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

And you run it like:

你像这样运行它:

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

Of course, that last option doesn't give you a portable docker image that you can give someone with your server, since your code is outsidethe image, on a volume.

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

Lots of options!

很多选择!

回答by punkrockpolly

For me this worked:

对我来说这有效:

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

My debian image apt-get was getting a broken/old version of npm, so passing a download path fixed it.

我的 debian 映像 apt-get 的 npm 版本损坏/旧版本,因此传递下载路径修复了它。