How can I (best) install/add nodejs permanently into a (Jenkins) docker image?
The result is a docker image with both Jenkins and nodejs.
The purpose is to install nodejs as a Global Tool in the Jenkins container. To achieve the installation folder of nodejs has to be known.
I saw e.g. this solution, but what is the installation folder of Nodejs?
RUN curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash && \
sudo apt-get install -y nodejs
Adding nodejs (later) automatically at Jenkins build time is not a good thing, because it slows the build process down.
Installing nodejs on top of the jenkins image is the way to go. Adding an instruction to install nodejs inside the Dockefile is a standard thing in Docker to do when packaging dependencies.
Adding nodejs (later) automatically at Jenkins build time is not a
good thing, because it slows the build process down.
This is not always true. Docker builds use a cache for layers being created when building a Dockerfile. Thus if you install nodejs at the top of your Dockerfile, you will only have to wait once for the installation and the next build commands will just use the cache and there won't be any additional time required to install nodejs inside the Jenkins image.
I would recommend that you install nodejs inside the jenkins image using docker multi-stage builds. Since there already exists a Docker image for node, you can use that to install node inside the jenkins image.
FROM node as nodejs
FROM jenkins/jenkins
COPY --from=nodejs /usr/local/bin/node /usr/local/bin/node
By building the Dockerfile above, you will get an image with jenkins and node installed using the official node Docker image.
Besides the answers, please have a look to this superb solution. This allows install nodejs and npm. Now I can run 'npm' as a command in the shell. So, no need of the Global Tools usage is needed. Notice: it suggesets that using multiple FROM's is not a good practice (any more).
A very good addition is this piece of advice. If you need multiple node versions, you can also define them in your Jenkinsfile!