1- FROM node:20-alpine
1+ # ===== BUILD STAGE =====
2+ FROM node:20-alpine AS builder
23
34WORKDIR /app
45
5- # Install dependencies for better-sqlite3
6- RUN apk add --no-cache python3 make g++
6+ # Install system dependencies required for native module compilation,
7+ # plus curl and bash (needed to run the Bun installation script)
8+ RUN apk add --no-cache python3 make g++ curl bash
79
8- # Copy package files
10+ # Install Bun globally and relocate it to a shared, persistent location
11+ RUN curl -fsSL https://bun.sh/install | bash \
12+ && mv /root/.bun /opt/bun \
13+ && ln -s /opt/bun/bin/bun /usr/local/bin/bun
14+
15+ # Ensure Bun is available in PATH for subsequent commands
16+ ENV PATH="/opt/bun/bin:${PATH}"
17+
18+ # Copy package manifests to install dependencies
919COPY package*.json ./
10- RUN npm ci
1120
12- # Copy source code
21+ # Install all dependencies (including devDependencies) using Bun
22+ # --frozen-lockfile ensures reproducible builds
23+ # --concurrent-scripts and --network-concurrency optimize install speed
24+ RUN bun install --frozen-lockfile --concurrent-scripts=10 --network-concurrency=96
25+
26+ # Copy source code and build the application
1327COPY src/ ./src/
1428COPY tsconfig.json ./
29+ RUN bun run build
1530
16- # Build TypeScript
17- RUN npm run build
18-
19- # Remove dev dependencies for slimmer runtime image
31+ # Remove devDependencies to reduce image size
32+ # (Removing all the devDependencies that we dont need in the final build)
2033RUN npm prune --omit=dev
2134
22- # Create data directory
23- RUN mkdir -p /data && chown -R node:node /data
35+
36+ # ===== PRODUCTION STAGE =====
37+ FROM node:20-alpine AS production
38+
39+ WORKDIR /app
40+
41+ # Create a dedicated non-root user for security
42+ RUN addgroup -g 1001 -S appgroup \
43+ && adduser -u 1001 -S appuser -G appgroup
44+
45+ # Copy only production artifacts from the builder stage
46+ COPY --from=builder /app/node_modules ./node_modules/
47+ COPY --from=builder /app/dist ./dist/
48+ COPY package.json ./
49+
50+ # Create a directory for persistent data and secure file permissions
51+ RUN mkdir -p /data \
52+ && chown -R appuser:appgroup /data /app \
53+ && chmod -R go-w /app
2454
2555# Switch to non-root user
26- USER node
56+ USER appuser
2757
28- # Expose port
58+ # Expose the application port
2959EXPOSE 8080
3060
31- # Health check
61+ # Define a lightweight health check that verifies the /health endpoint
3262HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
3363 CMD node -e "require('http').get('http://localhost:8080/health', (res) => process.exit(res.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"
3464
35- # Start server
36- CMD ["npm" , "start" ]
65+ # Start the application using npm
66+ ENTRYPOINT ["npm" , "start" ]
0 commit comments