Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

npm ERR! Tracker "idealTree" already exists while creating the Docker image for Node project

This issue is happening due to changes in nodejs starting version 15. When no WORKDIR is specified, npm install is executed in the root directory of the container, which is resulting in this error. Executing the npm install in a project directory of the container specified by WORKDIR resolves the issue.

Use the following 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" ]

The correct answer is basically right, but when I tried it still didn't work. Here's why:

WORKDIR specifies the context to the COPY that follows it. Having already specified the context in ./usr/app it is wrong to ask to copy from ./ (the directory you are working in) to ./usr/app as this produces the following structure in the container: ./usr/app/usr/app.

As a result CMD ["npm", "start"], which is followed where specified by WORKDIR (./usr/app) does not find the package.json.

I suggest using this Dockerfile:

FROM node:alpine

WORKDIR /usr/app

COPY ./ ./

RUN npm install

CMD ["npm", "start"]

You should specify the WORKDIR prior to COPY instruction in order to ensure the execution of npm install inside the directory where all your application files are there. Here is how you can complete this:

WORKDIR /usr/app

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

Note that you can simply "COPY ./ (current local directory) ./ (container directory which is now /usr/app thanks to the WORKDIR instruction)" instead of "COPY ./ /usr/app"

Now the good reason to use WORKDIR instruction is that you avoid mixing your application files and directories with the root file system of the container (to avoid overriding file system directories in case you have similar directories labels on your application directories)

One more thing. It is a good practice to segment a bit your configuration so that when you make a change for example in your index.js (so then you need to rebuild your image), you will not need to run "npm install" while the package.json has not been modified.

Your application is very basic, but think of a big applications where "npm install" should take several minutes.

In order to make use of caching process of Docker, you can segment your configuration as follows:

WORKDIR /usr/app

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

This instructs Docker to cache the first COPY and RUN commands when package.json is not touched. So when you change for instance the index.js, and you rebuild your image, Docker will use cache of the previous instructions (first COPY and RUN) and start executing the second COPY. This makes your rebuild much quicker.

Example for image rebuild:

 => 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 ./ ./

# 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.This is also write if you change any of your index file and docker build and docker run it automatically change your new changes to your browser output


Global install

In the event you're wanting to install a package globally outside of working directory with a package.json, you should use the -g flag.

npm install -g <pkg>

This error may trigger if the CI software you're using like semantic-release is built in node and you attempt to install it outside of a working directory.


Building on the answer of Col, you could also do the following in your viewmodel:

public class IndexVM() {

   @AfterCompose
   public void doAfterCompose(@ContextParam(ContextType.COMPONENT) Component c) {
       Window wizard = (Window) c;
       Label label = (Label) c.getFellow("lblName");
       ....
   }
}

In doing so, you actually have access to the label object and can perform all sorts of tasks with it (label.setValue(), label.getValue(), etc.).


A bit late to the party, but for projects not wanting to create a Dockerfile for the installer, it is also possible to run the installer from an Ephemeral container. This gives full access to the Node CLI, without having to install it on the host machine.

The command assumes it is run from the root of the project and there is a package.json file present. The -v $(pwd):/app option mounts the current working directory to the /app folder in the container, synchronizing the installed files back to the host directory. The -w /app option sets the work directory of the image as the /app folder. The --loglevel=verbose option causes the output of install command to be verbose. More options can be found on the official Node docker hub page.

docker run --rm -v $(pwd):/app -w /app node npm install --loglevel=verbose

Personally I use a Makefile to store several Ephemeral container commands that are faster to run separate from the build process. But of course, anything is possible :)