1

I'm trying to deploy an application I wrote to my unraid server so I had to docker-ize it. It's written with nodejs and depends on imagemagick and ghostscript so I had to include a build step to install those dependencies. I'm seeing an error when running this image though

Here's my dockerfile

FROM node
RUN mkdir -p /usr/src/app
RUN chmod -R 777 /usr/src/app
WORKDIR /usr/src/app
COPY . /usr/src/app
RUN npm i --only=production
FROM ubuntu
RUN apt-get update
RUN apt-get install -y imagemagick ghostscript nodejs
ENTRYPOINT node /usr/src/app/index.js

Console output

internal/modules/cjs/loader.js:638
throw err;
^

Error: Cannot find module '/usr/src/app/index.js'

at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
at Function.Module._load (internal/modules/cjs/loader.js:562:25)
at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

Originally, my entrypoint was configured like ENTRYPOINT node ./index.js but I thought that I was in the wrong directory or something but switching to an absolute path didn't work either so here I am.

1 Answer 1

1

By using a second FROM instruction, you are introducing a second stage. Nothing from the first stage is available to the second stage by default. If you need some artefacts, you need to copy them explicitly.

# give the stage a name to 
# be able to reference it later
FROM node as builder
RUN mkdir -p /usr/src/app
RUN chmod -R 777 /usr/src/app
WORKDIR /usr/src/app
COPY . /usr/src/app
RUN npm i --only=production

# this is a new stage
FROM ubuntu
RUN apt-get update
RUN apt-get install -y imagemagick ghostscript nodejs
# you need to copy the things you need 
COPY --from=builder /usr/src/app /usr/src/app
ENTRYPOINT node /usr/src/app/index.js

That said, it seems pointless for a node app to do that. I would suggest using a single stage. The node runtime is required to run your app. Multi staging would make sense if you were to use node to build statics with something like webpack and then copy the produced statics into a second stage that doesn't need the node runtime.

Also note that using an entrypoint over a simple command only makes sense if your application takes additional arguments and flags, and you want the user of your image to be able to provide said arguments without being required to know how to start the actual app.

Another thing to improve is using npm ci over npm i to avoid untested behaviour in production.

The use of the 2 run instructions to create the folder and change its permissions seem also somewhat redundant. If you use a workdir, that folder is automatically created.

Sign up to request clarification or add additional context in comments.

3 Comments

Installing npm on the ubuntu build step seems to require input from the command line despite the -y option being enabled on the apt-get install step Here's my current dockerfile with changes made dockerfile FROM node as builder WORKDIR /usr/src/app COPY . /usr/src/app RUN npm ci --only=production FROM ubuntu RUN apt-get update RUN apt-get install -y imagemagick ghostscript nodejs COPY --from=builder /usr/src/app /usr/src/app ENTRYPOINT node index.js
ooh that's hard to read, sorry about that
@BrandonPina, its probably best to open a new question for that. I guess you have to find out how to install your package in a so called headless mode. That is, when its done by some automation where there is no human to provide inputs. It depends on what you are installing how this might look like.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.