# /!\\ NOTICE /!\\
# Many of the developers DO NOT USE the Dockerfile or image.
# While we do test new changes to Docker configuration, it's
# possible that future changes to the repo might break it.
# When changing this file, please try to make it as resiliant
# to such changes as possible; developers shouldn't need to
# worry about Docker unless the build/run process changes.
# Build stage
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set up working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the source files
COPY . .
# Install mocha
RUN npm i -g npm@latest
RUN npm install -g mocha
# Install node modules
RUN npm cache clean --force && \
for i in 1 2 3; do \
npm ci && break || \
if [ $i -lt 3 ]; then \
sleep 15; \
else \
LOG_DIR="$(npm config get cache | tr -d '\"')/_logs"; \
echo "npm install failed; dumping logs from $LOG_DIR"; \
if [ -d "$LOG_DIR" ]; then \
ls -al "$LOG_DIR" || true; \
cat "$LOG_DIR"/* || true; \
else \
echo "Log directory not found (npm cache: $(npm config get cache))"; \
fi; \
exit 1; \
fi; \
done
# Run the build command if necessary
RUN cd src/gui && npm run build && cd -
# Production stage
FROM node:24-alpine
# Set labels
LABEL repo="https://github.com/HeyPuter/puter"
LABEL license="AGPL-3.0,https://github.com/HeyPuter/puter/blob/master/LICENSE.txt"
LABEL version="1.2.46-beta-1"
# Install git (required by Puter to check version)
RUN apk add --no-cache git
# Set up working directory
RUN mkdir -p /opt/puter/app
WORKDIR /opt/puter/app
# Copy built artifacts and necessary files from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY . .
# Set permissions
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://puter.localhost:4100/test || exit 1
ENV NO_VAR_RUNTUME=1
# Attempt to fix `lru-cache@11.0.2` missing after build stage
# by doing a redundant `npm install` at this stage
RUN npm install
CMD ["npm", "start"]
# Exclude files and folders that are not needed for the Docker image .git .github node_modules dist build coverage .vscode .env *.log logs/ .dockerignore Dockerfile docker-compose.yml
Build timed out after 600s
# /!\\ NOTICE /!\\
# Many of the developers DO NOT USE the Dockerfile or image.
# While we do test new changes to Docker configuration, it's
# possible that future changes to the repo might break it.
# When changing this file, please try to make it as resiliant
# to such changes as possible; developers shouldn't need to
# worry about Docker unless the build/run process changes.
# Build stage
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set up working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the source files
COPY . .
# Install mocha
RUN npm i -g npm@latest
RUN npm install -g mocha
# Install node modules
RUN npm cache clean --force && \
for i in 1 2 3; do \
npm ci && break || \
if [ $i -lt 3 ]; then \
sleep 15; \
else \
LOG_DIR="$(npm config get cache | tr -d '\"')/_logs"; \
echo "npm install failed; dumping logs from $LOG_DIR"; \
if [ -d "$LOG_DIR" ]; then \
ls -al "$LOG_DIR" || true; \
cat "$LOG_DIR"/* || true; \
else \
echo "Log directory not found (npm cache: $(npm config get cache))"; \
fi; \
exit 1; \
fi; \
done
# Run the build command if necessary
RUN cd src/gui && npm run build && cd -
# Production stage
FROM node:24-alpine
# Set labels
LABEL repo="https://github.com/HeyPuter/puter"
LABEL license="AGPL-3.0,https://github.com/HeyPuter/puter/blob/master/LICENSE.txt"
LABEL version="1.2.46-beta-1"
# Install git (required by Puter to check version)
RUN apk add --no-cache git wget
# Set up working directory
RUN mkdir -p /opt/puter/app
WORKDIR /opt/puter/app
# Copy built artifacts and necessary files from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY . .
# Set permissions
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://puter.localhost:4100/test || exit 1
# Attempt to fix `lru-cache@11.0.2` missing after build stage
# by doing a redundant `npm install` at this stage
RUN npm install
CMD ["npm", "start"]
Build timed out after 600s
# /!\\ NOTICE /!\\
# Many of the developers DO NOT USE the Dockerfile or image.
# While we do test new changes to Docker configuration, it's
# possible that future changes to the repo might break it.
# When changing this file, please try to make it as resiliant
# to such changes as possible; developers shouldn't need to
# worry about Docker unless the build/run process changes.
# Build stage
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set up working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy only GUI source to speed up rebuilds
COPY src/gui ./src/gui
# Install mocha
RUN npm i -g npm@latest
RUN npm install -g mocha
# Install node modules
RUN npm cache clean --force && \
for i in 1 2 3; do \
npm ci && break || \
if [ $i -lt 3 ]; then \
sleep 15; \
else \
LOG_DIR="$(npm config get cache | tr -d '\"')/_logs"; \
echo "npm install failed; dumping logs from $LOG_DIR"; \
if [ -d "$LOG_DIR" ]; then \
ls -al "$LOG_DIR" || true; \
cat "$LOG_DIR"/* || true; \
else \
echo "Log directory not found (npm cache: $(npm config get cache))"; \
fi; \
exit 1; \
fi; \
done
# Run the build command if necessary
RUN cd src/gui && npm run build && cd -
# Production stage
FROM node:24-alpine
# Set labels
LABEL repo="https://github.com/HeyPuter/puter"
LABEL license="AGPL-3.0,https://github.com/HeyPuter/puter/blob/master/LICENSE.txt"
LABEL version="1.2.46-beta-1"
# Install git (required by Puter to check version) and wget for healthcheck
RUN apk add --no-cache git wget
# Set up working directory
RUN mkdir -p /opt/puter/app
WORKDIR /opt/puter/app
# Copy built artifacts and necessary files from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/node_modules ./node_modules
# Copy remaining runtime files from the repo (avoids including everything in the build context unnecessarily)
COPY package.json package-lock.json ./
COPY src ./src
COPY tools ./tools
COPY extensions ./extensions
COPY mods ./mods
COPY mod_packages ./mod_packages
# Set permissions
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Use localhost for healthcheck inside the container
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:4100/test || exit 1
ENV NO_VAR_RUNTUME=1
# Attempt to fix `lru-cache@11.0.2` missing after build stage
# by doing a redundant `npm install` at this stage
RUN npm install
CMD ["npm", "start"]
Failing step - [build 10/10] RUN cd src/gui && npm run build && cd - Exact error message and exit code - Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'yargs' imported from /app/src/gui/build.js - Node.js v24.14.0 - npm error code 1 - The run failed during: command sh -c node ./build.js - Docker exit code: 1 Missing packages or files mentioned - Missing package: yargs (imported by /app/src/gui/build.js) Version mismatch/info - Base image uses Node.js 24 (node:24-alpine); reported Node.js version during failure: v24.14.0 - The failure occurs in the src/gui build step, indicating a dependency resolution mismatch for yargs during the build script.
# /!\\ NOTICE /!\\
# Many of the developers DO NOT USE the Dockerfile or image.
# While we do test new changes to Docker configuration, it's
# possible that future changes to the repo might break it.
# When changing this file, please try to make it as resiliant
# to such changes as possible; developers shouldn't need to
# worry about Docker unless the build/run process changes.
# Build stage
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set up working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the source files
COPY . .
# Install mocha
RUN npm i -g npm@latest
RUN npm install -g mocha
# Install node modules
RUN npm cache clean --force && \
for i in 1 2 3; do \
npm ci && break || \
if [ $i -lt 3 ]; then \
sleep 15; \
else \
LOG_DIR="$(npm config get cache | tr -d '\"')/_logs"; \
echo "npm install failed; dumping logs from $LOG_DIR"; \
if [ -d "$LOG_DIR" ]; then \
ls -al "$LOG_DIR" || true; \
cat "$LOG_DIR"/* || true; \
else \
echo "Log directory not found (npm cache: $(npm config get cache))"; \
fi; \
exit 1; \
fi; \
done
# Install GUI dependencies for the build and build the GUI
RUN cd src/gui && npm ci
# Run the build command if necessary
RUN cd src/gui && npm run build && cd -
# Production stage
FROM node:24-alpine
# Set labels
LABEL repo="https://github.com/HeyPuter/puter"
LABEL license="AGPL-3.0,https://github.com/HeyPuter/puter/blob/master/LICENSE.txt"
LABEL version="1.2.46-beta-1"
# Install git (required by Puter to check version) and wget for healthcheck
RUN apk add --no-cache git wget
# Set up working directory
RUN mkdir -p /opt/puter/app
WORKDIR /opt/puter/app
# Copy built artifacts and necessary files from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/node_modules ./node_modules
# Copy remaining runtime files from the repo (keeps the runtime image leaner by excluding heavy dev files)
COPY package.json package-lock.json ./
COPY src ./src
COPY tools ./tools
COPY extensions ./extensions
COPY mods ./mods
COPY mod_packages ./mod_packages
# Set permissions
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Use localhost for healthcheck inside the container
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:4100/test || exit 1
ENV NO_VAR_RUNTIME=1
# Attempt to fix `lru-cache@11.0.2` missing after build stage
# by doing a redundant `npm install` at this stage
RUN npm install
CMD ["npm", "start"]
- Exact error message and exit code
- sh: husky: not found
- exit code: 127
- npm error code 127
- npm error path /app
- npm error command failed
- npm error command sh -c husky
- A complete log of this run can be found in: /root/.npm/_logs/2026-03-22T13_31_09_477Z-debug-0.log
- Failing command/step
- [build 10/11] RUN cd src/gui && npm ci
- Missing packages or files mentioned
- The Husky CLI ("husky") executable is not found during npm ci. The package puter.com@2.5.1 has a prepare script that runs husky, but the husky binary is not installed or not in PATH (i.e., node_modules/.bin/husky is missing during the prepare step).
- Version mismatch information
- Base image used: node:24-alpine
- No explicit version mismatch reported in the log. The failure appears related to missing Husky binary rather than a Node/npm version incompatibility.# /!\\ NOTICE /!\\
# Many of the developers DO NOT USE the Dockerfile or image.
# While we do test new changes to Docker configuration, it's
# possible that future changes to the repo might break it.
# When changing this file, please try to make it as resiliant
# to such changes as possible; developers shouldn't need to
# worry about Docker unless the build/run process changes.
# Build stage
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set up working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the source files
COPY . .
# Install mocha
RUN npm i -g npm@latest
RUN npm install -g mocha
# Install node modules (including workspace dependencies)
RUN npm cache clean --force && \
for i in 1 2 3; do \
npm ci && break || \
if [ $i -lt 3 ]; then \
sleep 15; \
else \
LOG_DIR="$(npm config get cache | tr -d '\"')/_logs"; \
echo "npm install failed; dumping logs from $LOG_DIR"; \
if [ -d "$LOG_DIR" ]; then \
ls -al "$LOG_DIR" || true; \
cat "$LOG_DIR"/* || true; \
else \
echo "Log directory not found (npm cache: $(npm config get cache))"; \
fi; \
exit 1; \
fi; \
done
# Build GUI assets
RUN cd src/gui && npm run build && cd -
# Production stage
FROM node:24-alpine
# Install runtime dependencies required for healthcheck
RUN apk add --no-cache wget git
# Set labels
LABEL repo="https://github.com/HeyPuter/puter"
LABEL license="AGPL-3.0,https://github.com/HeyPuter/puter/blob/master/LICENSE.txt"
LABEL version="1.2.46-beta-1"
# Set up working directory
WORKDIR /opt/puter/app
# Copy built artifacts and necessary files from the build stage
COPY --from=build /app ./
# Set permissions
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Healthcheck against localhost inside the container
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:4100/test || exit 1
CMD ["npm", "start"]
Build timed out after 600s
Build timed out after 600s
# /!\\ NOTICE /!\\
# Many of the developers DO NOT USE the Dockerfile or image.
# While we do test new changes to Docker configuration, it's
# possible that future changes to the repo might break it.
# When changing this file, please try to make it as resiliant
# to such changes as possible; developers shouldn't need to
# worry about Docker unless the build/run process changes.
# Build stage
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set up working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the source files
COPY . .
# Install mocha
RUN npm i -g npm@latest
RUN npm install -g mocha
# Install node modules (including workspace dependencies)
RUN npm cache clean --force && \
for i in 1 2 3; do \
npm ci && break || \
if [ $i -lt 3 ]; then \
sleep 15; \
else \
LOG_DIR="$(npm config get cache | tr -d '\"')/_logs"; \
echo "npm install failed; dumping logs from $LOG_DIR"; \
if [ -d "$LOG_DIR" ]; then \
ls -al "$LOG_DIR" || true; \
cat "$LOG_DIR"/* || true; \
else \
echo "Log directory not found (npm cache: $(npm config get cache))"; \
fi; \
exit 1; \
fi; \
done
# Build GUI assets
RUN cd src/gui && npm run build && cd -
# Production stage
FROM node:24-alpine
# Install runtime dependencies required for healthcheck
RUN apk add --no-cache wget git
# Set labels
LABEL repo="https://github.com/HeyPuter/puter"
LABEL license="AGPL-3.0,https://github.com/HeyPuter/puter/blob/master/LICENSE.txt"
LABEL version="1.2.46-beta-1"
# Set up working directory
WORKDIR /opt/puter/app
# Copy built artifacts and necessary files from the build stage
COPY --from=build /app ./
# Set permissions
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Healthcheck against localhost inside the container
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:4100/test || exit 1
ENV NO_VAR_RUNTIME=1
# Attempt to fix `lru-cache@11.0.2` missing after build stage
# by doing a redundant `npm install` at this stage
RUN npm install
CMD ["npm", "start"]
Build timed out after 600s
# /!\\ NOTICE /!\\
# Many of the developers DO NOT USE the Dockerfile or image.
# While we do test new changes to Docker configuration, it's
# possible that future changes to the repo might break it.
# When changing this file, please try to make it as resiliant
# to such changes as possible; developers shouldn't need to
# worry about Docker unless the build/run process changes.
# Build stage
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set up working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the source files
COPY . .
# Install dependencies (ignore scripts to avoid Husky prepare steps during install)
RUN npm i -g npm@latest
RUN npm install -g mocha
RUN npm ci --ignore-scripts
# Build GUI assets if possible
RUN cd src/gui && npm run build || true
# Production stage
FROM node:24-alpine
# Install runtime dependencies required for healthcheck
RUN apk add --no-cache wget git
# Set labels
LABEL repo="https://github.com/HeyPuter/puter"
LABEL license="AGPL-3.0,https://github.com/HeyPuter/puter/blob/master/LICENSE.txt"
LABEL version="1.2.46-beta-1"
# Set up working directory
WORKDIR /opt/puter/app
# Copy built artifacts and necessary files from the build stage
COPY --from=build /app ./
# Set permissions
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Healthcheck against localhost inside the container
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:4100/test || exit 1
ENV NO_VAR_RUNTIME=1
CMD ["npm", "start"]
Build timed out after 600s
# /!\\ NOTICE /!\\
# Many of the developers DO NOT USE the Dockerfile or image.
# While we do test new changes to Docker configuration, it's
# possible that future changes to the repo might break it.
# When changing this file, please try to make it as resiliant
# to such changes as possible; developers shouldn't need to
# worry about Docker unless the build/run process changes.
# Build stage
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set up working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the source files (GUI and others needed for the build)
COPY . .
# Install dependencies and build GUI
RUN npm i -g npm@latest
RUN npm install -g mocha
# Install node modules (including workspace dependencies)
RUN npm cache clean --force && \
for i in 1 2 3; do \
npm ci && break || \
if [ $i -lt 3 ]; then \
sleep 15; \
else \
LOG_DIR="$(npm config get cache | tr -d '\"')/_logs"; \
echo "npm install failed; dumping logs from $LOG_DIR"; \
if [ -d "$LOG_DIR" ]; then \
ls -al "$LOG_DIR" || true; \
cat "$LOG_DIR"/* || true; \
else \
echo "Log directory not found (npm cache: $(npm config get cache))"; \
fi; \
exit 1; \
fi; \
done
# Build GUI assets
RUN cd src/gui && npm run build && cd -
# Production stage
FROM node:24-alpine
# Install runtime dependencies required for healthcheck
RUN apk add --no-cache wget
# Set labels
LABEL repo="https://github.com/HeyPuter/puter"
LABEL license="AGPL-3.0,https://github.com/HeyPuter/puter/blob/master/LICENSE.txt"
LABEL version="1.2.46-beta-1"
# Set up working directory
WORKDIR /opt/puter/app
# Copy built artifacts and necessary files from the build stage
COPY --from=build /app ./
# Set permissions
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Healthcheck against localhost inside the container
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:4100/test || exit 1
CMD ["npm", "start"]
Build timed out after 600s
# Stage 1: Build
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set working directory
WORKDIR /app
# Copy manifest files first to leverage cache
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the rest of the repository
COPY . .
# Install dependencies (including dev) to build the project
RUN npm ci
# Build GUI assets
RUN cd src/gui && npm run build && cd -
# Stage 2: Production
FROM node:24-alpine
# Install runtime dependencies
RUN apk add --no-cache curl git
# Environment
ENV APP_PORT=4100
ENV NO_VAR_RUNTIME=1
# Working directory for the production image
WORKDIR /opt/puter/app
# Copy manifests and install production dependencies only
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
# Copy built artifacts and necessary source from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/tools ./tools
COPY --from=build /app/src ./src
COPY --from=build /app/package.json ./package.json
COPY --from=build /app/package-lock.json ./package-lock.json
# Ensure proper permissions for the node user
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Robust healthcheck: try /health, then /test as a fallback
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s \
CMD sh -lc 'if curl -fsS http://127.0.0.1:4100/health; then exit 0; fi; if curl -fsS http://127.0.0.1:4100/test; then exit 0; fi; exit 1'
CMD ["node", "./tools/run-selfhosted.js"]
# Node modules and build artifacts node_modules/ dist/ build/ coverage/ .vscode/ *.log logs/ .cache/ .DS_Store .git/ .github/ .env .env.* Dockerfile docker-compose.yml README.md LICENSE.txt
Summary (under 1500 chars): - Failing command/step: - stage-1 5/11: RUN npm ci --omit=dev - Exact error message and exit code: - ERROR: process "/bin/sh -c npm ci --omit=dev" did not complete successfully: exit code: 127 - npm error code 127 - sh: husky: not found - npm error code 127 - npm error path /opt/puter/app - npm error command failed - npm error command sh -c husky - A complete log of this run can be found in: /root/.npm/_logs/2026-03-22T14_29_49_468Z-debug-0.log - Missing packages or files mentioned: - husky (not found) - Version mismatch / info: - npm notice New minor version of npm available! 11.9.0 -> 11.12.0 - (Deprecation/warnings present elsewhere in logs, but no explicit dependency version mismatch cited) Notes: - Root cause: npm ci --omit=dev excludes devDependencies, so Husky (invoked by the prepare script) is not installed, leading to “sh: husky: not found” during npm ci. To fix, avoid omitting devDependencies (e.g., npm ci without --omit=dev) or ensure Husky is available in production (e.g., as a production dependency or adjust the prepare script).
# Stage 1: Build
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set working directory
WORKDIR /app
# Copy manifest files first to leverage cache
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the rest of the repository
COPY . .
# Install dependencies (including dev) to build the project
RUN npm ci
# Build GUI assets
RUN cd src/gui && npm run build && cd -
# Stage 2: Production
FROM node:24-alpine
# Install runtime dependencies
RUN apk add --no-cache curl git
# Environment
ENV APP_PORT=4100
ENV NO_VAR_RUNTIME=1
# Working directory for the production image
WORKDIR /opt/puter/app
# Copy built artifacts and necessary source from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/src ./src
COPY --from=build /app/tools ./tools
COPY --from=build /app/package.json ./package.json
COPY --from=build /app/package-lock.json ./package-lock.json
# Ensure proper permissions for the node user
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Robust healthcheck: try /health, then /test as a fallback
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s \
CMD sh -lc 'if curl -fsS http://127.0.0.1:4100/health; then exit 0; fi; if curl -fsS http://127.0.0.1:4100/test; then exit 0; fi; exit 1'
CMD ["node", "./tools/run-selfhosted.js"]
Build timed out after 600s
# Stage 1: Build
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set working directory
WORKDIR /app
# Copy manifest files first to leverage cache
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the rest of the repository
COPY . .
# Install dependencies (including dev) to build the project
# Ignore scripts to avoid issues with Husky during build
RUN npm ci --ignore-scripts
# Build GUI assets
RUN cd src/gui && npm run build && cd -
# Stage 2: Production
FROM node:24-alpine
# Install runtime dependencies
RUN apk add --no-cache curl git
# Environment
ENV APP_PORT=4100
ENV NO_VAR_RUNTIME=1
# Working directory for the production image
WORKDIR /opt/puter/app
# Copy built artifacts and necessary source from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/src ./src
COPY --from=build /app/tools ./tools
COPY --from=build /app/package.json ./package.json
COPY --from=build /app/package-lock.json ./package-lock.json
# Ensure proper permissions for the node user
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Robust healthcheck: try /health, then /test as a fallback
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s \
CMD sh -lc 'if curl -fsS http://127.0.0.1:4100/health; then exit 0; fi; if curl -fsS http://127.0.0.1:4100/test; then exit 0; fi; exit 1'
CMD ["node", "./tools/run-selfhosted.js"]
Build timed out after 600s
# Stage 1: Build
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set working directory
WORKDIR /app
# Copy manifest files first to leverage cache
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the rest of the repository
COPY . .
# Install dependencies (including dev) to build the project
RUN npm ci
# Build GUI assets
RUN cd src/gui && npm run build && cd -
# Stage 2: Production
FROM node:24-alpine
# Install runtime dependencies
RUN apk add --no-cache curl
# Environment
ENV APP_PORT=4100
ENV NO_VAR_RUNTIME=1
# Working directory for the production image
WORKDIR /opt/puter/app
# Copy built artifacts and necessary source from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/src ./src
COPY --from=build /app/tools ./tools
COPY --from=build /app/package.json ./package.json
COPY --from=build /app/package-lock.json ./package-lock.json
# Ensure proper permissions for the node user
RUN addgroup -S node && adduser -S node -G node
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Robust healthcheck: try /health, then /test as a fallback
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s \
CMD sh -lc 'if curl -fsS http://127.0.0.1:4100/health; then exit 0; fi; if curl -fsS http://127.0.0.1:4100/test; then exit 0; fi; exit 1'
CMD ["node", "./tools/run-selfhosted.js"]
Summary (concise) - Failing step: stage-1 10/11 - Dockerfile: RUN addgroup -S node && adduser -S node -G node - Dockerfile reference: Dockerfile:48 - Exact error message and exit code - Error: addgroup: group 'node' in use - Exit code: 1 - Context about the failing command/step - Command: RUN addgroup -S node && adduser -S node -G node - Version/base image details (relevant to the failure) - Base image used: node:24-alpine (with explicit SHA: sha256:7fddd9ddeae8196abf4a3ef2de34e11f7b1a722119f91f28ddf1e99dcafdf114) - Observation: The group 'node' already exists in the base image, causing addgroup to fail. - Missing packages or files mentioned - None directly missing in the error; the only related note is a prior log line during npm install: ".git can't be found" (not the cause of the failure). - Version mismatch information - No explicit version mismatch indicated beyond using the node:24-alpine base image referenced above.
# Stage 1: Build
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set working directory
WORKDIR /app
# Copy manifest files first to leverage cache
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the rest of the repository
COPY . .
# Install dependencies (including dev) to build the project
RUN npm ci
# Build GUI assets
RUN cd src/gui && npm run build && cd -
# Stage 2: Production
FROM node:24-alpine
# Install runtime dependencies
RUN apk add --no-cache curl
# Environment
ENV APP_PORT=4100
ENV NO_VAR_RUNTIME=1
# Working directory for the production image
WORKDIR /opt/puter/app
# Copy built artifacts and necessary source from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/src ./src
COPY --from=build /app/tools ./tools
COPY --from=build /app/package.json ./package.json
COPY --from=build /app/package-lock.json ./package-lock.json
# Ensure proper permissions for the node user
# Use the existing 'node' user from the base image to avoid conflicts
USER node
EXPOSE 4100
# Robust healthcheck: try /health, then /test as a fallback
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s \
CMD sh -lc 'if curl -fsS http://127.0.0.1:4100/health; then exit 0; fi; if curl -fsS http://127.0.0.1:4100/test; then exit 0; fi; exit 1'
CMD ["node", "./tools/run-selfhosted.js"]
Concerns: Final image may be larger due to copying build artifacts (node_modules, src) into production; consider pruning or multi-stage packaging to reduce size., Healthcheck relies on /health or /test endpoints; if the app changes its endpoints, healthcheck may become invalid. Smoke [PASS]: test -d /opt/puter/app/dist Smoke [FAIL]: curl -fsS http://127.0.0.1:4100/health Output: curl: (7) Failed to connect to 127.0.0.1 port 4100 after 0 ms: Could not connect to server Smoke [FAIL]: curl -fsS http://127.0.0.1:4100/test Output: curl: (7) Failed to connect to 127.0.0.1 port 4100 after 0 ms: Could not connect to server
- Purpose: Node.js launcher for Puter backend. Imports modules from @heyputer/backend, constructs a Kernel, registers modules (EssentialModules plus several default modules), and boots the kernel. Optional DevelopmentModule is loaded if UNSAFE_PUTER_DEV is set.
- Node.js version requirement: Node.js 16 or newer. If major < 16, prints a red boxed message:
- “Please use a version of Node.js 16 or newer.”
- “Issues with node X.Y.Z:”
- Possible reasons (for major < under):
- under 14: optional chaining is not available
- under 16: disk usage package ABI mismatch
- Exits with code 1.
- Optional dotenv: Attempts to import dotenv/config; not required.
- Entry path handling: Uses import.meta.filename as entry_path; includes a polyfill for import.meta.filename if missing.
- Modules loaded (via @heyputer/backend default export):
- Kernel
- EssentialModules (instantiated in a loop)
- DatabaseModule
- LocalDiskStorageModule
- MemoryStorageModule
- SelfHostedModule
- BroadcastModule
- TestDriversModule
- TestConfigModule
- PuterAIModule
- InternetModule
- DNSModule
- DevelopmentModule (only if process.env.UNSAFE_PUTER_DEV)
- Startup behavior: main() boots the kernel after wiring modules.
- Early init error handling:
- If the error message matches any of:
- "Cannot find package '@heyputer/backend'"
- Notes: "this usually happens if you forget `npm install`"
- Suggestions: "try running `npm install`"
- Technical notes: "@heyputer/backend is in an npm workspace"
- "Cannot find package"
- Notes: same as above
- Suggestions: same as above
- "Cannot write to path"
- Notes: "this usually happens when /var/puter isn't chown'd to the right UID"
- Suggestions: "check issue #645 on our github"
- For a match, prints a detailed help block and rethrows the error.
- Commands and actions to ensure smooth startup:
- npm install (in repo/workspace) to install @heyputer/backend
- Run the script (node <entry_file>), ensuring dependencies are installed
- To enable DevelopmentModule, set UNSAFE_PUTER_DEV=1 (e.g., UNSAFE_PUTER_DEV=1 node <entry_file>)
- Key files/strings to note in logs:
- Node version check logic and messages
- Early init error texts and notes:
- "Cannot find package '@heyputer/backend'"
- "Cannot find package"
- "Cannot write to path" (issues with /var/puter)
- Packages mentioned:
- @heyputer/backend
- Internal module names: Kernel, EssentialModules, DatabaseModule, LocalDiskStorageModule, MemoryStorageModule, SelfHostedModule, BroadcastModule, TestDriversModule, TestConfigModule, PuterAIModule, InternetModule, DevelopmentModule, DNSModule
- Boxed error output: uses a surrounding_box function to render error lines in a red box with Unicode borders.# Stage 1: Build
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set working directory
WORKDIR /app
# Copy manifest files first to leverage cache
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the rest of the repository
COPY . .
# Install dependencies (including dev) to build the project
RUN npm ci
# Prune devDependencies to prepare production dependencies
RUN npm prune --omit=dev
# Build GUI assets
RUN cd src/gui && npm run build && cd -
# Stage 2: Production
FROM node:24-alpine
# Install runtime dependencies
RUN apk add --no-cache curl
# Environment
ENV APP_PORT=4100
ENV NO_VAR_RUNTIME=1
# Working directory for the production image
WORKDIR /opt/puter/app
# Copy built artifacts and necessary source from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/src ./src
COPY --from=build /app/tools ./tools
COPY --from=build /app/package.json ./package.json
COPY --from=build /app/package-lock.json ./package-lock.json
# Ensure proper permissions for the node user
# Use the existing 'node' user from the base image to avoid conflicts
USER node
EXPOSE 4100
# Robust healthcheck: try /health, then /test as a fallback
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s \
CMD sh -lc 'if curl -fsS http://127.0.0.1:4100/health; then exit 0; fi; if curl -fsS http://127.0.0.1:4100/test; then exit 0; fi; exit 1'
CMD ["node", "./tools/run-selfhosted.js"]
Failing step:
- [build 9/9] RUN cd src/gui && npm run build && cd -; exited with code 1
Exact error message and exit code:
- Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'webpack' imported from /app/src/gui/utils.js
Node.js v24.14.0
(exit code: 1)
Relevant stack excerpt:
- Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'webpack' imported from /app/src/gui/utils.js
...
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:621:35)
...
at ModuleJob.syncLink (node:internal/modules/esm/module_job:160:33) {
code: 'ERR_MODULE_NOT_FOUND'
}
Missing packages or files mentioned:
- webpack is not found. This likely results from pruning dev dependencies in the image (npm prune --omit=dev), removing webpack which is used during the GUI build.
Version/mismatch information:
- Base image uses Node.js v24 (node:24-alpine); the log shows Node.js v24.14.0 during the failure.
Root cause (summary):
- The GUI build step requires webpack, but it was removed by npm prune --omit=dev in a prior step, leaving webpack unavailable at build time.
Suggestions to fix:
- Do not prune devDependencies before running the GUI build, or move webpack to dependencies (not devDependencies) so it remains installed.
- Alternative: perform the GUI build in a separate stage with devDependencies installed (no prune), or install webpack explicitly in the final image if needed at runtime.
- If webpack is only needed for build, ensure npm ci/install runs without --omit=dev for the GUI build step.# Stage 1: Build
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set working directory
WORKDIR /app
# Copy manifest files first to leverage cache
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the rest of the repository
COPY . .
# Install dependencies (including dev) to build the project
RUN npm ci
# Build GUI assets
RUN cd src/gui && npm run build && cd -
# Stage 2: Production
FROM node:24-alpine
# Install runtime dependencies
RUN apk add --no-cache curl
# Environment
ENV APP_PORT=4100
ENV NO_VAR_RUNTIME=1
# Working directory for the production image
WORKDIR /opt/puter/app
# Copy manifests and install production dependencies
COPY package.json package-lock.json ./
RUN npm ci
# Copy built artifacts and necessary source from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/src ./src
COPY --from=build /app/tools ./tools
COPY --from=build /app/package.json ./package.json
COPY --from=build /app/package-lock.json ./package-lock.json
# Ensure proper permissions for the node user
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Robust healthcheck: try /health, then /test as a fallback
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s \
CMD sh -lc 'if curl -fsS http://127.0.0.1:4100/health; then exit 0; fi; if curl -fsS http://127.0.0.1:4100/test; then exit 0; fi; exit 1'
CMD ["node", "./tools/run-selfhosted.js"]
Build timed out after 600s
# Stage 1: Build
FROM node:24-alpine AS build
# Install build dependencies
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Set working directory
WORKDIR /app
# Copy manifest files first to leverage cache
COPY package.json package-lock.json ./
# Fail early if lockfile or manifest is missing
RUN test -f package.json && test -f package-lock.json
# Copy the rest of the repository
COPY . .
# Install dependencies (including dev) to build the project
RUN npm ci
# Build GUI assets
RUN cd src/gui && npm run build && cd -
# Stage 2: Production
FROM node:24-alpine
# Install runtime dependencies
RUN apk add --no-cache curl
# Environment
ENV APP_PORT=4100
ENV NO_VAR_RUNTIME=1
# Working directory for the production image
WORKDIR /opt/puter/app
# Copy built artifacts and necessary source from the build stage
COPY --from=build /app/src/gui/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/tools ./tools
COPY --from=build /app/package.json ./package.json
COPY --from=build /app/package-lock.json ./package-lock.json
# Copy additional runtime requirements from the build stage if needed
# (we rely on the node_modules installed in the build stage for runtime)
# Ensure proper permissions for the node user
# Use the existing 'node' user from the base image to avoid conflicts
USER node
EXPOSE 4100
# Robust healthcheck: try /health, then /test as a fallback
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s \
CMD sh -lc 'if curl -fsS http://127.0.0.1:4100/health; then exit 0; fi; if curl -fsS http://127.0.0.1:4100/test; then exit 0; fi; exit 1'
CMD ["node", "./tools/run-selfhosted.js"]
Concerns: Build step may not install GUI dependencies if src/gui has its own package.json; npm ci is run only at root, not inside src/gui, Copying node_modules from the build stage may not include GUI-specific modules if they are installed in a subdirectory; ensure GUI dependencies are included in the final image, The GUI dist path assumption (dist under /dist) depends on the build script; verify run-selfhosted.js expects dist at that location Smoke [PASS]: test -d /opt/puter/app/dist Smoke [PASS]: test -f /opt/puter/app/tools/run-selfhosted.js Smoke [PASS]: test -f /opt/puter/app/package.json