## Multi-stage Dockerfile for building the TypeScript server FROM node:20-alpine AS builder WORKDIR / # Copy package files and install (in container only) COPY server/package*.json ./server/ WORKDIR /server RUN npm ci --silent # Copy server source and build COPY server/ ./ RUN npm run build ## Production image FROM node:20-alpine AS runtime # Allow host UID/GID to be specified at build time. ARG HOST_UID=1000 ARG HOST_GID=1000 WORKDIR / # Copy built server COPY --from=builder /server/dist ./server/dist COPY --from=builder /server/node_modules ./server/node_modules COPY server/package*.json /server/ ## Create hostuser in runtime image so runtime-created files have proper uid/gid RUN if ! getent group ${HOST_GID} >/dev/null 2>&1; then \ addgroup -g ${HOST_GID} hostgroup; \ else \ echo "group for GID ${HOST_GID} already exists"; \ fi RUN if ! getent passwd ${HOST_UID} >/dev/null 2>&1; then \ adduser -D -u ${HOST_UID} -G hostgroup hostuser; \ else \ echo "user for UID ${HOST_UID} already exists"; \ mkdir -p /home/hostuser || true; \ fi RUN chown -R ${HOST_UID}:${HOST_GID} /server || true WORKDIR /server ENV NODE_ENV=production ENV HOME=/home/hostuser USER ${HOST_UID}:${HOST_GID} EXPOSE 8930 CMD ["npm", "start"]