Trying to test out multistage builds in Docker for my nodejs app and I keep running into
internal/modules/cjs/loader.js:983
throw err;
^
Error: Cannot find module '/service/dist/server/server.js'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:980:15)
at Function.Module._load (internal/modules/cjs/loader.js:862:27)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)
at internal/main/run_main_module.js:18:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
My Dockerfile
FROM mybaseimage as dev
WORKDIR /service
COPY src ./src
COPY package*.json ./
COPY yarn.lock ./
COPY tsconfig.json ./
# This is required to build native modules
# https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#node-gyp-alpine
RUN apk add --no-cache \
g \
make \
py3-pip
# Not clearing the cache here saves us time in the next step
RUN yarn install \
&& yarn compile
# Re-use the dev container to create a production-ready node_modules dir
FROM dev AS build
WORKDIR /service
RUN rm -rf /service/node_modules\
&& yarn install --production=true \
&& yarn cache clean
FROM mybaseimage AS prod
WORKDIR /service
COPY --from=build /service/dist/ .
COPY --from=build /service/node_modules/ .
# https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#handling-kernel-signals
RUN apk add --no-cache dumb-init
EXPOSE 5678
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["node", "dist/server/server.js"]
My package.json
"serve": "node dist/server/server.js",
"start": "concurrently \"docker-compose up\" \"yarn watch\"",
My earlier working Dockerfile was
FROM mybaseimage
#set working directory
WORKDIR /service
# Copy the needed files into the container
COPY src ./src
COPY package*.json ./
COPY yarn.lock ./
COPY tsconfig.json ./
RUN apk update
RUN apk add python3
RUN echo python3 --version
RUN yarn install
RUN yarn compile
EXPOSE 5678
ENTRYPOINT ["npm", "run", "serve"]
CodePudding user response:
In the final stage, you are COPY
ing the dist
and node_modules
trees from the build stage into the current directory. You need to explicitly state the subdirectory names on the right-hand side of COPY
.
COPY --from=build /service/dist/ ./dist/
COPY --from=build /service/node_modules/ ./node_modules/
Also see the Dockerfile reference on COPY
: since the COPY
source is a directory, the contents of the directory are copied to the destination and not the directory itself. This differs from the normal Unix cp
or mv
commands.
You should be able to verify this running a debugging container on top of your built image; for example
docker run --rm your-image ls
should show the server
subdirectory from the build dist
tree, as well as all of the individual installed Node packages, all directly in the image's /service
directory and not in subdirectories.