在为Node项目创建Docker镜像时,出现了“idealTree”跟踪器已经存在的错误。

187

我创建了一个名为simpleWeb的node.js项目。该项目包含package.json和index.js两个文件。

index.js

    const express = require('express');
    
    const app = express();
    
    app.get('/', (req, res) => {
      res.send('How are you doing');
    });
    
    app.listen(8080, () => {
      console.log('Listening on port 8080');
    });

包描述文件


    {
        "dependencies": {
          "express": "*"
        },
        "scripts": {
          "start": "node index.js"
        }
      }

我还创建了一个Dockerfile来为我的node.js项目创建docker镜像。

Dockerfile

# Specify a base image
FROM node:alpine

# Install some dependencies 
COPY ./ ./
RUN npm install

# Default command
CMD ["npm", "start"]
在尝试使用“docker build .”命令构建Docker镜像时,它会抛出以下错误。 错误日志
simpleweb » docker build .                                                    ~/Desktop/jaypal/Docker and Kubernatise/simpleweb
[+] Building 16.9s (8/8) FINISHED
 => [internal] load build definition from Dockerfile                                                                         0.0s
 => => transferring dockerfile: 37B                                                                                          0.0s
 => [internal] load .dockerignore                                                                                            0.0s
 => => transferring context: 2B                                                                                              0.0s
 => [internal] load metadata for docker.io/library/node:alpine                                                               8.7s
 => [auth] library/node:pull token for registry-1.docker.io                                                                  0.0s
 => [internal] load build context                                                                                            0.0s
 => => transferring context: 418B                                                                                            0.0s
 => [1/3] FROM docker.io/library/node:alpine@sha256:5b91260f78485bfd4a1614f1afa9afd59920e4c35047ed1c2b8cde4f239dd79b         0.0s
 => CACHED [2/3] COPY ./ ./                                                                                                  0.0s
 => ERROR [3/3] RUN npm install                                                                                              8.0s
------
 > [3/3] RUN npm install:
#8 7.958 npm ERR! Tracker "idealTree" already exists
#8 7.969
#8 7.970 npm ERR! A complete log of this run can be found in:
#8 7.970 npm ERR!     **/root/.npm/_logs/2020-12-24T16_48_44_443Z-debug.log**
------
executor failed running [/bin/sh -c npm install]: exit code: 1

上面的日志文件提供了一个路径 "/root/.npm/_logs/2020-12-24T16_48_44_443Z-debug.log",我可以在其中找到完整的日志记录。

但是,这个文件在我的本地机器上不存在。

我不明白问题出在哪里。


6
请勿更改先前提出的问题,使其成为一个具有完全不同问题的新问题。之前给出的答案现在无法回答您修改后的问题。如果您有新的问题,请创建一个新的问题。请注意保持问题清晰和明确。 - Col
4
从 Node 版本 > 14 开始,你需要在 Dockerfile 中指定 WORKDIR。如果你不想在 Dockerfile 中提及 WORKDIR,请使用 Node 版本 <= 14。 - Ravi Singh
关于你所说的“上述文件在我的本地机器上不存在”的部分,请注意应该在容器中打开日志文件,而不是在你的本地机器上。你可以通过运行docker run -it node:alpine sh来启动容器,这将在图像node:alpine之外为你提供一个正在运行的容器内的Shell。然后,在该Shell中执行npm install,这将导致相同的错误,并最终访问前面提到的日志文件。 - Geralt
15个回答

381

由于 NodeJS 版本 15 开始的更改,导致出现了此问题。当未指定 WORKDIR 时,会在容器的根目录中执行 npm install,从而导致此错误。在由 WORKDIR 指定的容器项目目录中执行 npm install 可解决此问题。

请使用以下 Dockerfile

# Specify a base image
FROM node:alpine

#Install some dependencies

WORKDIR /usr/app
COPY ./ /usr/app
RUN npm install

# Set up a default command
CMD [ "npm","start" ]

1
请确保解释为什么一个答案可行,这样其他人就可以根据自己的用例进行调整。 - shakram02
10
由于Node.js从15版本开始的更改,导致出现了这个问题。如果未指定工作目录(WORKDIR),则npm install将在容器的根目录中执行,从而导致此错误。在容器内从项目目录中执行npm install可以解决此问题。请注意,不要改变原文的意思。 - Prince Arora
3
之前这个被存储的地方在哪里?这重要吗? - mjs
3
我还有点困惑,容器的根目录不是“/”吗?COPY ./ ./ 应该可以工作,因为我们正在将项目文件复制到根目录“/”。 - Thiago
1
现在是2023年,我认为这个解决方案已经不再有效了。尽管指定了WORKDIR,但它仍然无法正常工作。 - user1034912
显示剩余5条评论

39

全局安装

如果您想在工作目录以外全局安装包,而且没有 package.json 文件,则应使用 -g 标志。

npm install -g <pkg>

如果您正在使用像semantic-release这样的基于node的CI软件,并且尝试在工作目录之外安装它,则可能会触发此错误。


29

正确答案基本正确,但当我尝试时仍然无法工作。原因如下:

WORKDIR 指定了随后的 COPY 的上下文。已经在 ./usr/app 中指定了上下文,在要求从 ./(您正在其中工作的目录)复制到 ./usr/app 时是错误的,因为这会在容器中产生以下结构:./usr/app/usr/app

因此,CMD ["npm", "start"]WORKDIR./usr/app)指定的地方后面跟着,找不到 package.json

我建议使用这个 Dockerfile:

FROM node:alpine

WORKDIR /usr/app

COPY ./ ./

RUN npm install

CMD ["npm", "start"]

2
他使用了 /usr/app 而不是 ./usr/app。在后一种情况下,你最终会创建重复的子目录。 - Deekshith Anand
4
为什么在复制所有源文件后要运行npm i命令,这样不会缓存?我建议您了解Docker层以及为什么应该将层按从最不经常更改到最经常更改的顺序排序。 - Andreas Bergström

6

为了确保在执行npm install时在包含所有应用程序文件的目录中进行,请在COPY指令之前指定WORKDIR。以下是如何完成此操作:

你可以这样做:

WORKDIR /usr/app

# Install some dependencies
COPY ./ ./
RUN npm install

请注意,您可以简单地“COPY ./(当前本地目录)./(现在的容器目录是 /usr/app,感谢 WORKDIR 指令)”,而不是“COPY ./ /usr/app”。
使用 WORKDIR 指令的好处是,避免将应用程序文件和目录与容器的根文件系统混合在一起(以避免在应用程序目录中具有相似目录标签的情况下覆盖文件系统目录)。
还有一件事。很好的做法是略微分割配置,这样当您例如更改了 index.js(因此需要重建图像)时,您不需要运行“npm install”,而 package.json 尚未被修改。
尽管您的应用程序非常基本,但请考虑大型应用程序,其中 “npm install” 可需要数分钟。
为了利用 Docker 的缓存过程,您可以将配置划分如下:
WORKDIR /usr/app

# Install some dependencies
COPY ./package.json ./
RUN npm install
COPY ./ ./ 

这会让Docker在未更新package.json时缓存第一次执行的COPY和RUN命令。因此,当您更改例如index.js并重新构建图像时,Docker将使用先前指令(首个COPY和RUN)的缓存,并开始执行第二个COPY。 这使得重新构建速度更快。

图像重建示例:

 => CACHED [2/5] WORKDIR /usr/app                                                                                                       0.0s
 => CACHED [3/5] COPY ./package.json ./                                                                                                 0.0s
 => CACHED [4/5] RUN npm install                                                                                                        0.0s
 => [5/5] COPY ./ ./

5
有些项目不想为安装程序创建 Dockerfile,可以在 临时容器 中运行安装程序。这样可以完全访问 Node 命令行界面,而无需在主机上安装它。
该命令假定从项目的根目录运行,并存在 package.json 文件。选项 -v $(pwd):/app 将当前工作目录挂载到容器中的 /app 文件夹,将已安装的文件同步回主机目录。选项 -w /app 将镜像的工作目录设置为 /app 文件夹。选项 --loglevel=verbose 会使安装命令的输出详细。更多选项可以在官方 Node docker hub 页面找到。
docker run --rm -v $(pwd):/app -w /app node npm install --loglevel=verbose

个人而言,我使用一个 Makefile 存储几个短暂容器命令,这些命令在构建过程中单独运行更快。但当然,任何事情都有可能 :)

4

在Dockerfile中指定工作目录如下将会生效:

WORKDIR '/app'

确保在docker-compose命令中使用 --build 重新从 Dockerfile 构建:
docker-compose up --build

2
这个问题被严重低估了。Node镜像不会在根目录下执行“npm install”,所以你需要使用另一个目录。 - johnnyb

4
# Specify a base image
FROM node:alpine

WORKDIR /usr/app

# Install some dependencies
COPY ./package.json ./
RUN npm install
COPY ./ ./

# Default command
CMD ["npm","start"]

1. 如果您更改任何索引文件并进行docker构建和docker运行,它也会自动将新变更更改为浏览器输出。


2
也许你可以更改Node版本。此外,不要忘记WORKDIR。
FROM node:14-alpine
WORKDIR /usr/app
COPY ./ ./
RUN npm install
CMD ["npm", "start"]

0
我们也遇到了类似的问题,所以我用 'yarn' 替换了 npm,效果不错。这是示例代码。
FROM python:3.7-alpine

ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1
#install bash
RUN apk --update add bash zip yaml-dev
RUN apk add --update nodejs yarn build-base postgresql-dev gcc python3- 
dev musl-dev libffi-dev
RUN yarn config set prefix ~/.yarn



#install serverless
RUN yarn global add serverless@2.49.0 --prefix /usr/local && \
yarn global add serverless-pseudo-parameters@2.4.0 && \
yarn global add serverless-python-requirements@4.3.0


RUN mkdir -p /code
WORKDIR /code

COPY requirements.txt .
COPY requirements-test.txt .

RUN pip install --upgrade pip
RUN pip install -r requirements-test.txt

COPY . .

CMD ["bash"]

0

你可以指定 Node 版本小于 15。

# Specify a base image
FROM node:14

# Install some dependencies 
COPY ./ ./
RUN npm install

# Default command
CMD ["npm", "start"]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接