Use a multistage Dockerfile #1

Open
opened 2025-09-01 10:33:58 +01:00 by Ghost · 1 comment
Ghost commented 2025-09-01 10:33:58 +01:00 (Migrated from codeberg.org)

Normally I'd want to make a multistage Dockerfile so that Yarn wasn't present in the final image. However, something was going wrong where if I installed production dependencies in a buildstage and copied them over via COPY, Node.js would fail to find the modules.

Meanwhile, installing directly into the final image was fine.

I will investigate this later as it's not a priority.

My original Dockerfile:

FROM node:22.19.0-alpine3.22 AS build

WORKDIR /home/node

# Copy package management files to restore node_modules.
COPY package.json yarn.lock .yarnrc.yml ./

RUN corepack enable && \
    yarn workspaces focus --all --production

FROM node:22.19.0-trixie-slim
LABEL maintainer="seth@falco.fun"

WORKDIR /home/node

# Copy health files and source code.
COPY LICENSE package.json README.md ./
COPY src/ ./src/
# Copy installed node_modules from previous build stage.
COPY --from=build /home/node/node_modules/ ./node_modules/

RUN npm install --global ./
USER 1000

ENTRYPOINT ["matrix-stream-alerts"]

The error:

node@73fce258e644:~$ matrix-stream-alerts 
node:internal/modules/cjs/loader:1383
  const err = new Error(message);
              ^

Error: Cannot find module '@matrix-org/matrix-sdk-crypto-nodejs-linux-x64-gnu'
Require stack:
- /home/node/node_modules/.store/@matrix-org-matrix-sdk-crypto-nodejs-npm-0.1.0-beta.6-283d8fa90e/package/index.js
- /home/node/node_modules/.store/matrix-bot-sdk-npm-0.7.1-6b01a33c60/package/lib/e2ee/CryptoClient.js
    at Function._resolveFilename (node:internal/modules/cjs/loader:1383:15)
    at defaultResolveImpl (node:internal/modules/cjs/loader:1025:19)
    at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1030:22)
    at Function._load (node:internal/modules/cjs/loader:1192:37)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:237:24)
    at Module.require (node:internal/modules/cjs/loader:1463:12)
    at require (node:internal/modules/helpers:147:16)
    at Object.<anonymous> (/home/node/node_modules/.store/@matrix-org-matrix-sdk-crypto-nodejs-npm-0.1.0-beta.6-283d8fa90e/package/index.js:190:31)
    at Module._compile (node:internal/modules/cjs/loader:1706:14) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/home/node/node_modules/.store/@matrix-org-matrix-sdk-crypto-nodejs-npm-0.1.0-beta.6-283d8fa90e/package/index.js',
    '/home/node/node_modules/.store/matrix-bot-sdk-npm-0.7.1-6b01a33c60/package/lib/e2ee/CryptoClient.js'
  ]
}

Node.js v22.19.0
Normally I'd want to make a multistage Dockerfile so that Yarn wasn't present in the final image. However, something was going wrong where if I installed production dependencies in a buildstage and copied them over via `COPY`, Node.js would fail to find the modules. Meanwhile, installing directly into the final image was fine. I will investigate this later as it's not a priority. My original Dockerfile: ```dockerfile FROM node:22.19.0-alpine3.22 AS build WORKDIR /home/node # Copy package management files to restore node_modules. COPY package.json yarn.lock .yarnrc.yml ./ RUN corepack enable && \ yarn workspaces focus --all --production FROM node:22.19.0-trixie-slim LABEL maintainer="seth@falco.fun" WORKDIR /home/node # Copy health files and source code. COPY LICENSE package.json README.md ./ COPY src/ ./src/ # Copy installed node_modules from previous build stage. COPY --from=build /home/node/node_modules/ ./node_modules/ RUN npm install --global ./ USER 1000 ENTRYPOINT ["matrix-stream-alerts"] ``` The error: ``` node@73fce258e644:~$ matrix-stream-alerts node:internal/modules/cjs/loader:1383 const err = new Error(message); ^ Error: Cannot find module '@matrix-org/matrix-sdk-crypto-nodejs-linux-x64-gnu' Require stack: - /home/node/node_modules/.store/@matrix-org-matrix-sdk-crypto-nodejs-npm-0.1.0-beta.6-283d8fa90e/package/index.js - /home/node/node_modules/.store/matrix-bot-sdk-npm-0.7.1-6b01a33c60/package/lib/e2ee/CryptoClient.js at Function._resolveFilename (node:internal/modules/cjs/loader:1383:15) at defaultResolveImpl (node:internal/modules/cjs/loader:1025:19) at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1030:22) at Function._load (node:internal/modules/cjs/loader:1192:37) at TracingChannel.traceSync (node:diagnostics_channel:322:14) at wrapModuleLoad (node:internal/modules/cjs/loader:237:24) at Module.require (node:internal/modules/cjs/loader:1463:12) at require (node:internal/modules/helpers:147:16) at Object.<anonymous> (/home/node/node_modules/.store/@matrix-org-matrix-sdk-crypto-nodejs-npm-0.1.0-beta.6-283d8fa90e/package/index.js:190:31) at Module._compile (node:internal/modules/cjs/loader:1706:14) { code: 'MODULE_NOT_FOUND', requireStack: [ '/home/node/node_modules/.store/@matrix-org-matrix-sdk-crypto-nodejs-npm-0.1.0-beta.6-283d8fa90e/package/index.js', '/home/node/node_modules/.store/matrix-bot-sdk-npm-0.7.1-6b01a33c60/package/lib/e2ee/CryptoClient.js' ] } Node.js v22.19.0 ```
Ghost commented 2025-09-06 19:11:28 +01:00 (Migrated from codeberg.org)

We switched from pnpm node linker to node-modules. Figured I'd just see if that change would be enough to solve this, however it was not. I didn't give it an in-depth look this time, but this is the latest version of the Dockerfile anyway:

FROM node:22.19.0-alpine3.22 AS build

WORKDIR /home/node

# Copy package management files to restore node_modules.
COPY package.json yarn.lock .yarnrc.yml ./
COPY .yarn/ ./.yarn/

RUN corepack enable && \
    yarn workspaces focus --all --production

FROM node:22.19.0-trixie-slim
LABEL maintainer="seth@falco.fun"

WORKDIR /home/node

# Copy health files and source code.
COPY LICENSE package.json README.md ./
COPY src/ ./src/
# Copy installed node_modules from previous build stage.
COPY --from=build /home/node/node_modules/ ./node_modules/

RUN npm install --global ./
USER 1000

CMD ["matrix-stream-alerts"]

Same error!

We switched from pnpm node linker to node-modules. Figured I'd just see if that change would be enough to solve this, however it was not. I didn't give it an in-depth look this time, but this is the latest version of the Dockerfile anyway: ```dockerfile FROM node:22.19.0-alpine3.22 AS build WORKDIR /home/node # Copy package management files to restore node_modules. COPY package.json yarn.lock .yarnrc.yml ./ COPY .yarn/ ./.yarn/ RUN corepack enable && \ yarn workspaces focus --all --production FROM node:22.19.0-trixie-slim LABEL maintainer="seth@falco.fun" WORKDIR /home/node # Copy health files and source code. COPY LICENSE package.json README.md ./ COPY src/ ./src/ # Copy installed node_modules from previous build stage. COPY --from=build /home/node/node_modules/ ./node_modules/ RUN npm install --global ./ USER 1000 CMD ["matrix-stream-alerts"] ``` Same error!
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
SethFalco/matrix-stream-alerts#1
No description provided.