Skip to content

Commit 69a82eb

Browse files
committed
refactor: optimize Dockerfile copy operations and implement multi-stage build for showcase app
1 parent 69350d0 commit 69a82eb

7 files changed

Lines changed: 93 additions & 90 deletions

File tree

apps/app/Dockerfile

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# syntax=docker/dockerfile:1.23.0
22

3-
43
# FROM oven/bun:1.3.2-alpine AS builder
54
# Use node because of bun issue blocking at `Creating an optimized production build ...`
65
# https://github.com/oven-sh/bun/issues/17136
@@ -63,20 +62,25 @@ ENV NODE_ENV=production
6362
# Build the app
6463
RUN bun run build && bun scripts/generate-sw.ts
6564

66-
# Create and use a non-root user for security
67-
RUN addgroup -S app && adduser -S app -G app && chown -R app:app ./.output
65+
# Runner — use oven/bun base image to avoid npm install overhead
66+
FROM oven/bun:1.3.12-alpine AS runner
67+
68+
RUN apk add --no-cache wget
69+
70+
WORKDIR /app
71+
72+
ENV NODE_ENV=production
73+
74+
RUN addgroup -S app && adduser -S app -G app
75+
76+
COPY --from=builder --chown=app:app /workspace/apps/app/.output ./.output
6877

6978
USER app
7079

7180
# Expose the API port (defaults to 3100 via .env, can be overridden)
7281
EXPOSE 3000
7382

74-
HEALTHCHECK CMD true
75-
76-
# HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
77-
# CMD \
78-
# wget -qO- http://localhost:3000/ > /dev/null || exit 1 && \
79-
# wget -qO- http://localhost:3000/doc/environment/nextjs > /dev/null || exit 1
83+
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
84+
CMD wget -qO- http://localhost:3000/ > /dev/null || exit 1
8085

81-
# Start the app server
8286
CMD ["bun", "run", ".output/server/index.mjs"]

apps/backend/Dockerfile

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# syntax=docker/dockerfile:1.23.0
22

3-
FROM node:22-alpine AS builder
3+
# Base stage: system deps shared between builder and runner
4+
FROM node:22-alpine AS base
45

56
RUN npm install -g bun@1.3.12
67

@@ -23,7 +24,9 @@ ENV PUPPETEER_SKIP_DOWNLOAD=true
2324
ENV PUPPETEER_CACHE_DIR=/home/app/.cache/puppeteer
2425
ENV TMPDIR=/workspace/apps/backend/tmp
2526

26-
# Create app directory
27+
# Builder stage
28+
FROM base AS builder
29+
2730
WORKDIR /workspace
2831

2932
# Copy the monorepo, excluding packages not needed by the backend
@@ -65,7 +68,7 @@ COPY \
6568
--exclude=examples \
6669
--exclude=apps/website \
6770
--exclude=apps/showcase \
68-
--exclude=apps/app \
71+
--exclude=apps/app \
6972
--exclude=apps/doc \
7073
--exclude=**/*.stories.* \
7174
. .
@@ -75,22 +78,24 @@ COPY docs/blog/en/ docs/blog/en/
7578
COPY docs/frequent_questions/en/ docs/frequent_questions/en/
7679
COPY docs/legal/en/ docs/legal/en/
7780

78-
# Install all dependencies (dev + prod) for the backend filter
7981
RUN bun install --ignore-scripts --filter=./apps/backend
8082

81-
# Build every package needed by the backend
8283
RUN bun x turbo run build:ci --filter=./apps/backend
8384

84-
# Strip source files to keep the image slim
85+
# Strip source files to reduce image size
8586
RUN find . -path "*/src/*" -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.map" \) -not -path "*/node_modules/*" -delete
8687

88+
# Runner stage — inherits system deps (chromium etc.) from base
89+
FROM base AS runner
90+
8791
ENV NODE_ENV=production
8892

89-
# Create a non-root user for security
9093
RUN addgroup -S app && adduser -S app -G app
9194

9295
RUN mkdir -p /workspace/apps/backend/tmp /home/app/.cache/puppeteer && \
93-
chown -R app:app /workspace/apps/backend /home/app/.cache
96+
chown -R app:app /workspace /home/app/.cache
97+
98+
COPY --from=builder --chown=app:app /workspace /workspace
9499

95100
WORKDIR /workspace/apps/backend
96101

@@ -99,8 +104,7 @@ USER app
99104
# Expose the API port
100105
EXPOSE 3100
101106

102-
HEALTHCHECK CMD true
103-
# HEALTHCHECK --interval=10s --timeout=5s --start-period=120s --retries=5 \
104-
# CMD wget --no-verbose --tries=1 --spider http://localhost:3100/health || exit 1
107+
HEALTHCHECK --interval=10s --timeout=5s --start-period=120s --retries=5 \
108+
CMD wget --no-verbose --tries=1 --spider http://localhost:3100/health || exit 1
105109

106-
CMD ["bun", "dist/esm/index.mjs"]
110+
CMD ["bun", "dist/esm/index.mjs"]

apps/doc/Dockerfile

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# syntax=docker/dockerfile:1.23.0
22

3-
43
# FROM oven/bun:1.3.2-alpine AS builder
54
# Use node because of bun issue blocking at `Creating an optimized production build ...`
65
# https://github.com/oven-sh/bun/issues/17136
@@ -45,7 +44,6 @@ COPY \
4544
--exclude=plugins \
4645
--exclude=docs/assets \
4746
--exclude=examples \
48-
--exclude=plugins \
4947
--exclude=**/*.stories.* \
5048
. .
5149

@@ -63,20 +61,27 @@ ENV NODE_ENV=production
6361
# Build the doc app
6462
RUN bun run build && bun scripts/generate-sw.ts
6563

66-
# Create and use a non-root user for security
67-
RUN addgroup -S app && adduser -S app -G app && chown -R app:app ./.output
64+
# Runner — use oven/bun base image to avoid npm install overhead
65+
FROM node:22-alpine AS runner
66+
67+
RUN npm install -g bun@1.3.12
68+
69+
RUN apk add --no-cache wget
70+
71+
WORKDIR /app
72+
73+
ENV NODE_ENV=production
74+
75+
RUN addgroup -S app && adduser -S app -G app
76+
77+
COPY --from=builder --chown=app:app /workspace/apps/doc/.output ./.output
6878

6979
USER app
7080

71-
# Expose the API port (defaults to 3100 via .env, can be overridden)
7281
EXPOSE 3000
7382

74-
HEALTHCHECK CMD true
75-
76-
# HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
77-
# CMD \
78-
# wget -qO- http://localhost:3000/ > /dev/null || exit 1 && \
79-
# wget -qO- http://localhost:3000/doc/environment/nextjs > /dev/null || exit 1
83+
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
84+
CMD \
85+
wget -qO- http://localhost:3000/ > /dev/null || exit 1
8086

81-
# Start the doc server
8287
CMD ["bun", "run", ".output/server/index.mjs"]

apps/showcase/Dockerfile

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,32 @@ ENV NODE_ENV=production
6363
# Build the showcase app
6464
RUN bun run build
6565

66-
# Create and use a non-root user for security
67-
RUN addgroup -S app && adduser -S app -G app && chown -R app:app ./.output
6866

69-
USER app
67+
# Runner
68+
FROM node:22-alpine AS runner
69+
70+
# Install bun in the runner stage as well
71+
RUN npm install -g bun@1.3.12
72+
73+
WORKDIR /app
74+
75+
ENV NODE_ENV=production
76+
77+
# Create a non-root user for security
78+
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
79+
80+
# Copy ONLY the built output from the builder stage
81+
COPY --from=builder --chown=appuser:appgroup /workspace/apps/showcase/.output ./.output
82+
83+
USER appuser
7084

71-
# Expose the API port (defaults to 3100 via .env, can be overridden)
7285
EXPOSE 3000
7386

74-
HEALTHCHECK CMD true
87+
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
88+
CMD \
89+
wget -qO- http://localhost:3000/ > /dev/null || exit 1 && \
90+
wget -qO- http://localhost:3000/doc/environment/nextjs > /dev/null || exit 1
7591

76-
# HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
77-
# CMD \
78-
# wget -qO- http://localhost:3000/ > /dev/null || exit 1 && \
79-
# wget -qO- http://localhost:3000/doc/environment/nextjs > /dev/null || exit 1
8092

8193
# Start the showcase server
82-
CMD ["bun", "run", ".output/server/index.mjs"]
94+
CMD ["bun", "run", ".output/server/index.mjs"]

apps/website/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ RUN addgroup -S appgroup && adduser -S appuser -G appgroup
106106

107107
# Copy only the standalone output and necessary static files from builder
108108
COPY --from=builder --chown=appuser:appgroup /workspace/apps/website/.next/standalone ./
109-
COPY --from=builder --chown=appuser:appgroup /workspace/apps/website/public ./apps/website/public
110-
COPY --from=builder --chown=appuser:appgroup /workspace/apps/website/.next/static ./apps/website/.next/static
109+
COPY --from=builder --chown=appuser:appgroup /workspace/apps/website/public ./public
110+
COPY --from=builder --chown=appuser:appgroup /workspace/apps/website/.next/static ./.next/static
111111

112112
USER appuser
113113

packages/@intlayer/design-system/Dockerfile

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
# syntax=docker/dockerfile:1.23.0
22

3-
########################
4-
# 1) Build stage
5-
########################
3+
# Builder stage
64
FROM node:22-alpine AS builder
75

86
RUN npm install -g bun@1.3.12
97

10-
# RUN apk add --no-cache nodejs npm wget
11-
128
# Put the repo in /workspace
139
WORKDIR /workspace
1410

@@ -41,7 +37,7 @@ COPY \
4137
--exclude=docs/frequent_questions \
4238
--exclude=docs/legal \
4339
--exclude=apps/website \
44-
--exclude=apps/app \
40+
--exclude=apps/app \
4541
--exclude=apps/doc \
4642
--exclude=apps/showcase \
4743
--exclude=plugins \
@@ -63,25 +59,17 @@ WORKDIR /workspace/packages/@intlayer/design-system
6359
# Build the intlayer dictionaries (optional if turbo already did what you need)
6460
RUN bun x intlayer build
6561

66-
HEALTHCHECK CMD true
67-
# HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
68-
# CMD \
69-
# wget -qO- http://localhost:6006/ > /dev/null || exit 1
70-
71-
72-
73-
# Build Storybook to a deterministic path to simplify the copy in the next stage
7462
ENV STORYBOOK_TELEMETRY=false
7563
ENV STORYBOOK_STATIC=true
7664
RUN bun x storybook build --disable-telemetry
7765

78-
########################
79-
# 2) Runtime
80-
########################
81-
FROM node:22-alpine
66+
# Runner — plain node + serve; no bun needed for static file serving
67+
FROM node:22-alpine AS runner
8268

8369
RUN npm install -g bun@1.3.12
8470

71+
RUN npm install -g serve && apk add --no-cache wget
72+
8573
WORKDIR /www
8674

8775

@@ -90,10 +78,8 @@ COPY --from=builder /workspace/packages/@intlayer/design-system/storybook-static
9078

9179
EXPOSE 6006
9280

93-
HEALTHCHECK CMD true
94-
# HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
95-
# CMD \
96-
# wget -qO- http://localhost:6006/ > /dev/null || exit 1
81+
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
82+
CMD wget -qO- http://localhost:6006/ > /dev/null || exit 1
9783

9884
# -f foreground, -p port, -h doc root
9985
CMD ["bun", "x", "serve", ".", "-l", "6006"]

packages/@intlayer/mcp/Dockerfile

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# syntax=docker/dockerfile:1.23.0
22

3-
43
# FROM oven/bun:1.3.2-alpine AS builder
54
# Use node because of bun issue blocking at `Creating an optimized production build ...`
65
# https://github.com/oven-sh/bun/issues/17136
@@ -9,13 +8,8 @@ FROM node:22-alpine AS builder
98

109
RUN npm install -g bun@1.3.12
1110

12-
# Create app directory
1311
WORKDIR /workspace
1412

15-
# RUN apk add --no-cache wget
16-
17-
# Copy the rest of the source code
18-
# Remove directories to keep the image slim
1913
COPY \
2014
--exclude=packages/@intlayer/vue-compiler \
2115
--exclude=packages/@intlayer/svelte-compiler \
@@ -53,7 +47,7 @@ COPY \
5347
--exclude=apps/website \
5448
--exclude=apps/showcase \
5549
--exclude=apps/app \
56-
--exclude=apps/doc \
50+
--exclude=apps/doc \
5751
--exclude=**/*.stories.* \
5852
. .
5953

@@ -69,35 +63,33 @@ RUN bun install
6963
# Build every package in the workspace (uses the root "build" script)
7064
RUN bun x turbo run build:ci --filter=./packages/@intlayer/mcp
7165

72-
# Remove all dev dependencies
73-
# RUN CI=true bun pm prune --production
74-
75-
# Remove .ts, .tsx and .map files only within src/** directories, ignoring node_modules, so configuration files like intlayer.config.ts are kept
66+
# Strip source files to reduce image size
7667
RUN find . -path "*/src/*" -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.map" \) -not -path "*/node_modules/*" -delete
7768

69+
# Runner — use oven/bun base image to avoid npm install overhead
70+
FROM node:22-alpine AS runner
71+
72+
RUN npm install -g bun@1.3.12
73+
74+
75+
WORKDIR /app
7876

7977
ENV NODE_ENV=production
8078

81-
# Create and use a non-root user for security
8279
RUN addgroup -S app && adduser -S app -G app
8380

84-
RUN chown -R app:app /workspace/packages/@intlayer/mcp
85-
86-
WORKDIR /workspace/packages/@intlayer/mcp
81+
COPY --from=builder --chown=app:app /workspace/packages/@intlayer/mcp/dist ./dist
82+
COPY --from=builder --chown=app:app /workspace/packages/@intlayer/mcp/package.json ./package.json
83+
COPY --from=builder --chown=app:app /workspace/node_modules ./node_modules
8784

8885
USER app
8986

9087
# Expose the API port
9188
EXPOSE 3000
9289

90+
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
91+
CMD wget -qO- http://localhost:3000/health > /dev/null || exit 1
9392

94-
HEALTHCHECK CMD true
95-
# HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
96-
# CMD \
97-
# wget -qO- http://localhost:3000/health > /dev/null || exit 1
98-
99-
# Option 1: Use mcp-proxy (recommended - simpler)
10093
CMD ["bun", "run", "start:sse"]
101-
10294
# Option 2: Use stdio transport (alternative)
10395
# CMD ["bun", "run", "start:stdio"]

0 commit comments

Comments
 (0)