Install nodejs and npm in Dockerfile
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.
Stefan
Updated on July 18, 2022Comments
-
Stefan almost 2 years
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 doingapt-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/*
-
Stefan almost 4 yearsThanks for the link I will have a look to that! I don't think the caching is the problem though since I am already using the --no-cache flag. I even tried not to use docker-compose so using:
sudo docker build --no-cache .
but that still gives me the same problem. And after running it in one RUN statement I still get the old node version installed and the repo not being added. -
chash almost 4 years@Stefan Sorry, I missed that you were already using
--no-cache
. See my edit for a potential solution. -
Stefan almost 4 yearsThanks a lot! I didn't realize I was silencing the output, I thought it was being executed successfully. I don't understand why sometimes the docker build fails when there is an error (like when using a shell comand that isn't installed) and other times it happily continues. Or is it because I was using
-s
for the curl command? -
chash almost 4 years
-s
was hiding the error output, but the reason Docker continued is because the exit status of thecurl https://<url> | bash
command is actually the exit status ofbash
(0 in this case). To cause the pipeline to fail because of curl's non-zero exit status, you would need to tweak the default shell to e.g.bash
and useset -o pipefail
:SHELL ["/bin/bash", "-o", "pipefail", "-c"]
.