# /!\ NOTICE /!\
# 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) 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 . .
# 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 node_modules and build artifacts for context node_modules/ dist/ .vscode/ .git/ *.log npm-debug.log* Dockerfile docker-compose.yml packages/ # npm cache .npm/
Build timed out after 600s
# /!\ NOTICE /!\
# 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 --no-audit --no-fund && 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 . .
# 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
# Remove stray env var to avoid runtime confusion
# 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 /!\\
# 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 --no-audit --no-fund && 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/. .
# Set permissions
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Healthcheck to ensure the service is up
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1: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 /!\\
# 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 --no-audit --no-fund && 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 /opt/puter/app
# Set permissions
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Healthcheck to ensure the service is up
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
# /!\\ NOTICE /!\\
# 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 (exclude files in .dockerignore)
COPY . .
# Install node modules
# Use npm ci for reproducible installs; skip extra tooling to save time
RUN npm ci --no-audit --no-fund
# Run the build command (GUI)
RUN cd src/gui && npm run build && cd -
# Production stage
FROM node:24-alpine
# Install runtime tools needed by the container (git for version checks, wget for healthchecks)
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 ./
# Set permissions
RUN chown -R node:node /opt/puter/app
USER node
EXPOSE 4100
# Healthcheck against localhost to avoid external DNS requirements
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
# Multi-stage build for Puter
# Build stage: install dependencies and build GUI
FROM node:24-alpine AS build
# Install build tools
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Working directory for build
WORKDIR /app
# Copy manifest and lockfile first for better caching
COPY package.json package-lock.json ./
# Fail-fast if manifest files are missing
RUN test -f package.json && test -f package-lock.json
# Copy the full source for build steps
COPY . .
# Upgrade npm and install mocha globally (for tests if needed)
RUN npm i -g npm@latest
RUN npm install -g mocha
# Install dependencies; retry to tolerate transient network issues
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 the GUI assets
RUN cd src/gui && npm run build && cd -
# Production stage: runtime image
FROM node:24-alpine
# Install minimal runtime dependencies
RUN apk add --no-cache git
# Prepare runtime working directory
RUN mkdir -p /opt/puter/app
WORKDIR /opt/puter/app
# Bring over built artifacts and runtime dependencies from the build stage
COPY --from=build /app /opt/puter/app
# Ensure proper ownership for the node user
RUN chown -R node:node /opt/puter/app
USER node
# Expose the application port
EXPOSE 4100
# A reasonable runtime environment variable; keep as a harmless flag
ENV NO_VAR_RUNTIME=1
# Start the application
CMD ["npm", "start"]
# Ignore local development artifacts .git node_modules .dist dist coverage .env .DS_Store npm-debug.log .npmrc .github *.log logs .Build*
Build timed out after 600s
# Multi-stage build for Puter
# Build stage: install dependencies and build GUI
FROM node:24-alpine AS build
# Install build tools
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Working directory
WORKDIR /app
# Copy manifest and lockfile first for better caching
COPY package.json package-lock.json ./
# Fail-fast if manifest files are missing
RUN test -f package.json && test -f package-lock.json
# Copy the full source for build steps
COPY . .
# Install dependencies
RUN npm ci
# Build the GUI assets
RUN cd src/gui && npm run build && cd -
# Production stage: runtime image
FROM node:24-alpine
# Install minimal runtime dependencies
RUN apk add --no-cache git
# Prepare runtime working directory
RUN mkdir -p /opt/puter/app
WORKDIR /opt/puter/app
# Bring over 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 . .
# Ensure proper ownership for the node user
RUN chown -R node:node /opt/puter/app
USER node
# Expose the application port
EXPOSE 4100
# Start the application
CMD ["npm", "start"]
Build timed out after 600s
# Multi-stage build for Puter
# Build stage: install dependencies and build GUI
FROM node:24-alpine AS build
# Install build tools
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Working directory
WORKDIR /app
# Copy manifest and lockfile first for better caching
COPY package.json package-lock.json ./
# Fail-fast if manifest files are missing
RUN test -f package.json && test -f package-lock.json
# Copy the full source for build steps
COPY . .
# Install dependencies
RUN npm ci
# Build the GUI assets
RUN cd src/gui && npm run build && cd -
# Production stage: runtime image
FROM node:24-alpine
# Install minimal runtime dependencies
RUN apk add --no-cache git curl
# Prepare runtime working directory
RUN mkdir -p /opt/puter/app
WORKDIR /opt/puter/app
# Bring over 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 . .
# Ensure proper ownership for the node user
RUN chown -R node:node /opt/puter/app
USER node
# Expose the application port
EXPOSE 4100
# Start the application
CMD ["npm", "start"]
Build timed out after 600s
# Multi-stage build for Puter
# Build stage: install dependencies and build GUI
FROM node:24-alpine AS build
# Install build tools
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Working directory
WORKDIR /app
# Copy manifest and lockfile first for better caching
COPY package.json package-lock.json ./
# Fail-fast if manifest files are missing
RUN test -f package.json && test -f package-lock.json
# Copy the full source for build steps
COPY . .
# Install dependencies
RUN npm ci
# Build the GUI assets
RUN cd src/gui && npm run build && cd -
# Production stage: runtime image
FROM node:24-alpine
# Install minimal runtime dependencies
RUN apk add --no-cache git curl
# Prepare runtime working directory
RUN mkdir -p /opt/puter/app
WORKDIR /opt/puter/app
# Bring over built artifacts and necessary files from the build stage
COPY --from=build /app /opt/puter/app
# Ensure proper ownership for the node user
RUN chown -R node:node /opt/puter/app
USER node
# Expose the application port
EXPOSE 4100
# Start the application
CMD ["npm", "start"]
Build timed out after 600s
# Multi-stage build for Puter
# Build stage: install dependencies and build GUI
FROM node:24-alpine AS build
# Install build tools
RUN apk add --no-cache git python3 make g++ \
&& ln -sf /usr/bin/python3 /usr/bin/python
# Working directory
WORKDIR /app
# Copy manifest and lockfile first for better caching
COPY package.json package-lock.json ./
# Fail-fast if manifest files are missing
RUN test -f package.json && test -f package-lock.json
# Copy the full source for build steps
COPY . .
# Install dependencies
RUN npm ci
# Build the GUI assets
RUN cd src/gui && npm run build && cd -
# Production stage: runtime image
FROM node:24-alpine
# Install minimal runtime dependencies
RUN apk add --no-cache curl
# Prepare runtime working directory
WORKDIR /app
# Bring over built artifacts and necessary files from the build stage
COPY --from=build /app /app
# Ensure proper ownership for the non-root user
RUN adduser -D appuser
USER appuser
# Expose the application port
EXPOSE 4100
# Start the application
CMD ["npm", "start"]
Concerns: The runtime build relies on a package-lock.json existing; if the repo uses npm install without a lockfile, the npm ci step will fail., Assumes the GUI build outputs assets into a location copied into /app by the --from=build stage; if the output path is different, the runtime may run without assets., The app must listen on 0.0.0.0:4100 for Docker port mapping to work; if it binds only to 127.0.0.1, external access will fail. Smoke [PASS]: test -f /app/package.json Smoke [PASS]: node -v Smoke [PASS]: npm start & PID=$!; sleep 3; if curl -sSf http://127.0.0.1:4100/; then echo 'server up'; else echo 'server down'; fi; kill $PID