Install nodejs and npm in Dockerfile - node.js

The context
I have a Dockerfile to create an image that contains an apache webserver. However I also want to build my website using the Dockerfile so that the build process isn't dependent on the developers local environment. Note that the docker container is only going to be used for local development not for production.
The problem
I have this Dockerfile:
FROM httpd
RUN apt-get update -yq
RUN apt-get -yq install curl gnupg
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash
RUN apt-get update -yq
RUN apt-get install -yq \
dh-autoreconf=19 \
ruby=1:2.5.* \
ruby-dev=1:2.5.* \
nodejs
I build it:
sudo docker build --no-cache .
The build completes successfully, here is part of the output:
Step 9/15 : RUN curl -sL https://deb.nodesource.com/setup_12.x | bash
---> Running in e6c747221ac0
......
......
......
Removing intermediate container 5a07dd0b1e01
---> 6279003c1e80
Successfully built 6279003c1e80
However, when I run the image in a container using this:
sudo docker container run --rm -it --name=debug 6279003c1e80 /bin/bash
Then when doing apt-cache policy inside the container, it doesn't show the repository that should have been added with the curl command. Also when doing apt-cache policy nodejs it shows the old version is installed.
However when I then run the following inside the container:
curl -sL https://deb.nodesource.com/setup_12.x | bash
apt-cache policy
apt-cache policy nodejs
It shows me the repository is added and it shows the newer nodejs version is available.
So why is it that when using the curl command using RUN inside the docker file it doesn't seem to work, but when doing it manually in the container from a shell then it does work? And how can I get around this problem?
Updates
Note that to prevent caching issues I am using the --no-cache flag.
I also removed all containers and did sudo docker system prune and rebuild the image but without success.
I tried bundling everything in one RUN command as user "hmm" suggested (as this is best practice for apt commands):
RUN apt-get update -yq \
&& apt-get -yq install curl gnupg && \
&& curl -sL https://deb.nodesource.com/setup_12.x | bash \
&& apt-get update -yq \
&& apt-get install -yq \
dh-autoreconf=19 \
ruby=1:2.5.* \
ruby-dev=1:2.5.* \
nodejs \
&& rm -rf /var/lib/apt/lists/*

You're likely running into issues with cached layers. There's a long section in the Dockerfile best practices documentation on using apt-get. Probably worth a read.
The gist is that Docker doesn't recognize any difference between the first and second RUN apt-get update, nor does it know that apt-get install depends on a fresh apt-get update layer.
The solution is to combine all of that into a single RUN command (recommended) or disable the cache during the build process (docker build --no-cache).
RUN apt-get update -yq \
&& apt-get -yq install curl gnupg ca-certificates \
&& curl -L https://deb.nodesource.com/setup_12.x | bash \
&& apt-get update -yq \
&& apt-get install -yq \
dh-autoreconf=19 \
ruby=1:2.5.* \
ruby-dev=1:2.5.* \
nodejs
Edit: Running your Dockerfile locally, I noticed no output from the curl command. After removing the -s flag (fail silently), you can see it's failing due to not being able to verify the server's SSL certificate:
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
The solution to that issue is to install ca-certificates before running curl. I've updated the RUN command above.

Related

How to run Database services in Docker container?

Trying to build an docker image to install Node and databases in image.
Databases are installed but services are not running while trying to go for container logs ..
FROM ubuntu:lastest
RUN apt-get update && apt-get install -y curl wget gnupg && \
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv D68FA50FEA312927 && \
echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-3.2.list && \
curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
apt-get update && \
apt-get install -y nodejs mongodb-org redis-server && \
node -v && \
npm -v
Please do help regarding this issue, i am new to Docker.
Best run the database containers separate, e.g. one container for mongodb and one for redis. Then connect your application container to those containers (either by links (deprecated) or by creating and sharing a network as discussed in this question. You also do not to have to start from ubuntu:latest, but can start with a node image like nodejs. Some 'orchestration', like docker-compose, can make a task of plugging these services together much easier, see this tutorial (the postgres database in the article can easily be exchanged by mongodb and redis). Also consider reading the best practices for Dockerfile writing.
You need to actually start mongod, e.g. like
apt-get install -y nodejs mongodb-org redis-server && \
mongod --fork && \
node -v && \
npm -v
But bear in mind that mongo should be configured first and it requires some time to spin up.
As a side note it is considered a better practice to compose individual single-purpose docker images rather than pack both database and application in a single image.
Please read https://docs.docker.com/compose/overview/

How to refresh your shell when using a Dockerfile?

I am trying to build a Dockerfile that can make use of Azure functions. After unsuccessfully trying to build it using alpine:3.9 because of library issues, I swapped to ubuntu:18.04. Now I have a problem in that I can't install nvm (node version manager) in such a way that I can install node. My Dockerfile is below. I have managed to install nvm but now, while trying to use nvm, I cannot install the node version I want. The problem probably has to do with refreshing the shell but that is tricky to do as it appears that Docker continues to use the original shell it entered to run the next build stages. Any suggestions on how to refresh the shell so nvm can work effectively?
FROM ubuntu:18.04
RUN apt update && apt upgrade -y && apt install -qq -y --no-install-recommends \
python-pip \
python-setuptools \
wget \
build-essential \
libssl-dev
RUN pip install azure-cli
RUN wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash
RUN . /root/.nvm/nvm.sh && nvm install 10.14.1 && node
ENTRYPOINT ["/bin/bash"]
After install nvm command put:
SHELL ["/bin/bash", "--login" , "-c"]
RUN nvm install 17
SHELL ["/bin/sh", "-c"]
Default shell is sh and first command switches it to bash. Parameter --login is required as you want to source .bashrc.
As all subsequent commands would be executed with changed shell it's good to switch it back to sh if you don't need it anymore.
You usually don't need version managers like nvm in a Docker image. Since a Docker image packages only a single application, and since it has its own isolated filesystem, you can just install the single version of Node you need.
The first thing I'd try is to just install whatever version of Node the standard Ubuntu package has (in Ubuntu 18.04, looks like 8.11). While there are some changes between Node versions, for the most part the language and core library have been pretty stable.
RUN apt update && apt-install nodejs
Or, if you need something newer, there are official Debian packages:
RUN curl -sSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - \
&& echo "deb https://deb.nodesource.com/node_10.x cosmic main" > /etc/apt/sources.list.d/nodesource.list \
&& apt update \
&& apt install nodejs
This will give you a current version of that major version of Node (as of this writing, 10.15.1).
If you really need that specific version of Node, there are official binary packages. I might write:
FROM ubuntu:18.04
ARG node_version=10.14.1
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive \
apt-get install --no-install-recommends --assume-yes \
ca-certificates \
curl \
xz-utils
RUN cd /usr/local \
&& curl -o- https://nodejs.org/dist/v${node_version}/node-v${node_version}-linux-x64.tar.xz \
| tar xJf - --strip 1
...where the last couple of lines unpack the Node tarball directly into /usr/local.

Cant launch chrome in docker linux container

I have an asp.net core application that uses the jsreport nuget packages to run reports. I am attempting to deploy it with a linux docker container. I seem to be having trouble getting chrome to launch when I run a report. I am getting the error:
Failed to launch chrome! Running as root without --no-sandbox is not supported.
I have followed the directions on the .net local reporting page (https://jsreport.net/learn/dotnet-local) regarding docker, but I am still getting the error.
Here is my full docker file:
#use the .net core 2.1 runtime default image
FROM microsoft/dotnet:2.1-aspnetcore-runtime
#set the working directory to the server
WORKDIR /server
#copy all contents in the current directory to the container server directory
COPY . /server
#install node
RUN apt-get update -yq \
&& apt-get install curl gnupg -yq \
&& curl -sL https://deb.nodesource.com/setup_8.x | bash \
&& apt-get install nodejs -yq
#install jsreport-cli
RUN npm install jsreport-cli -g
#install chrome for jsreport linux
RUN apt-get update && \
apt-get install -y gnupg libgconf-2-4 wget && \
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' && \
apt-get update && \
apt-get install -y google-chrome-unstable --no-install-recommends
ENV chrome:launchOptions:executablePath google-chrome-unstable
ENV chrome:launchOptions:args --no-sandbox
#expose port 80
EXPOSE 80
CMD dotnet Server.dll
Is there another step that I am missing somewhere?
Its little late but may be can help someone else.
For me, the only option that was needed to fix this issue in the docker container was to run chrome in a headless mode (so cause was in tests not in dockerfile).
ChromeOptions options = new ChromeOptions().setHeadless(true);
WebDriver driver = new ChromeDriver(options);
Results: Now tests run successfully, without any errors.
Expanding on Pramod's answer, my own issues were only solved by running with both the --headless and --no-sandbox flags.

Trouble installing NodeJS on Kali Linux docker image

I am trying to create a docker image based on the Kali Linux base image, and I need to install NodeJS as a dependency for my application.
Here's my Dockerfile:
FROM kalilinux/kali-linux-docker
RUN apt-get update -y && \
apt-get dist-upgrade -y && \
apt-get autoremove -y && \
apt-get clean -y
RUN apt-get install curl -y
RUN curl --silent --location https://rpm.nodesource.com/setup_8.x | bash - \
&& apt-get install nodejs -y
RUN npm i -g npm
ENV NODE_ENV production
WORKDIR /root/app
COPY . .
RUN npm i
EXPOSE 4000
ENTRYPOINT ["npm", "start"]
However, I hit the following error trying to install NodeJS:
Step 4/11 : RUN curl --silent --location https://rpm.nodesource.com/setup_8.x | bash - && apt-get install nodejs -y
---> Running in a63e56802eba
## Installing the NodeSource Node.js 8.x LTS Carbon repo...
## Inspecting system...
## You don't appear to be running an Enterprise Linux based system,
please contact NodeSource at https://github.com/nodesource/distributions/issues
if you think this is incorrect or would like your distribution to be considered
for support.
The command '/bin/sh -c curl --silent --location https://rpm.nodesource.com/setup_8.x | bash - && apt-get install nodejs -y' returned a non-zero code: 1
Admittedly I'm confused by a few things... namely that I was under the impression that NodeJS was already installed on Kali Linux (I have a VirtualBox VM using Debian 64-bit where it exists). I went as far as trying to install the kali-linux-all metapackage, but NodeJS/npm don't seem to exist.
Am I simply misunderstanding some basic premise of Docker and/or Kali Linux? Is there any other way to install NodeJS into my container?
I still don't fully understand why NodeJS is installed on my VM but not the base Kali docker image... but in any case I did manage to unblock myself.
First, I was pulling down a NodeJS installation script from nodesource which required rpm -- I found a different script that works without it. However the new script also required that I install gnupg.
Here's my updated Dockerfile:
FROM kalilinux/kali-linux-docker
RUN apt-get update -y && \
apt-get dist-upgrade -y && \
apt-get autoremove -y && \
apt-get clean -y
RUN apt-get -y install curl gnupg
RUN curl --silent --location https://deb.nodesource.com/setup_8.x | bash - \
&& apt-get install nodejs -y
RUN npm i -g npm
ENV NODE_ENV production
WORKDIR /root/app
COPY . .
RUN npm i
EXPOSE 4000
ENTRYPOINT ["npm", "start"]

Installing specific version of node.js and npm in ubuntu image with Dockerfile

I would like to know how can update my custom Dockerfile to install Node v6.3.1 and NPM v3.10.6 without breaking what is already in there.
Currently this is my custom file:
FROM ubuntu:16.10
MAINTAINER Fátima Alves
COPY . /my-software
WORKDIR /my-software
RUN apt-get update \
&& \
apt-get install -y \
python-dev \
tesseract-ocr
Thanks!
Update
Currently my dockerfile is like this:
FROM ubuntu:16.10
MAINTAINER Fátima Alves
COPY ./dist /my-software
COPY ./s3-config.json /my-software
COPY ./_* /my-software
COPY ./node_modules /my-software
WORKDIR /dataextractor
RUN apt-get update \
&& \
apt-get install -y \
curl
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - \
&& apt-get install -y nodejs
And is returning:
The command '/bin/sh -c curl -sL https://deb.nodesource.com/setup_6.x | bash - && apt-get install -y nodejs' returned a non-zero code: 1
Perhaps i'm missing something?
You can just follow the usual Ubuntu install instructions, just within the RUN statement in your Dockerfile
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - \
&& apt-get install -y nodejs
Docs
WHY
Because https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions suggests doing the "curl pipe bash" anti-pattern, let's try to make that cleaner.
WHAT
Since containers are built from a definitive OS and Version we don't need the universality of that bash script.
HOW
If we examine closely, the https://deb.nodesource.com/setup_6.x we see that it really only does 2 things for Debian:
Add their public key to apt's keychain via apt-key add
Add their deb repo to a newly created file /etc/apt/sources.list.d/nodesource.list
Adding sources
The 2nd thing we can do really easily. That is simply putting this in your Dockerfile:
COPY nodesource.list /etc/apt/sources.list.d/nodesource.list
Of course you'll need to create nodesource.list with content like:
deb https://deb.nodesource.com/node_6.x trusty main
deb-src https://deb.nodesource.com/node_6.x trusty main
Adding a trusted key
The 1st thing is a bit trickier to new "cleanly". I would rather to add a keychain file to /etc/apt/trusted.gpg.d/ than modify the existing /etc/apt/trusted.gpg file (which is what apt-key add would do).
What they have at the URL https://deb.nodesource.com/gpgkey/nodesource.gpg.key is a public key, not a keychain. To get a keychain file, we can pipe it [not to apt-key, rather] like so:
curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | \
gpg --import --no-default-keyring --keyring ./nodesource.gpg
That creates nodesource.gpg which we can utilize by putting this in your Dockerfile:
COPY nodesource.gpg /etc/apt/trusted.gpg.d/nodesource.gpg
Install as usual
The crazy spacing and \ terminated lines is what I use because I tend to have a lot of additional packages to install.
# Install software packages
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update -qq && apt-get clean
RUN apt-get install -qqy \
nodejs \
&& \
apt-get clean
You can see the complete Dockerfile at https://gist.github.com/RichardBronosky/f748563dc328b12b39cd864973fcb138#file-dockerfile

Resources