Repository navigation
Expand file tree
/
Copy pathDockerfile
More file actions
122 lines (94 loc) · 5.04 KB
/
Copy pathDockerfile
File metadata and controls
122 lines (94 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# ───────────────────────────────────────────────
# Stage 1: Frontend dependency install
# ───────────────────────────────────────────────
FROM oven/bun:1.4.0-alpine AS frontend-deps
RUN apk update && apk add --no-cache libc6-compat && rm -rf /var/cache/apk/*
WORKDIR /app
COPY apps/web/package.json apps/web/bun.lock* ./
RUN bun install --frozen-lockfile
# ───────────────────────────────────────────────
# Stage 2: Frontend build
# ───────────────────────────────────────────────
FROM oven/bun:1.4.0-alpine AS frontend-builder
WORKDIR /app
COPY --from=frontend-deps /app/node_modules ./node_modules
COPY apps/web .
# Disable telemetry during build
ENV NEXT_TELEMETRY_DISABLED=1
# Remove .env files to avoid leaking secrets into the build
RUN rm -f .env*
RUN bun run build
# ───────────────────────────────────────────────
# Stage 3: Frontend production image
# ───────────────────────────────────────────────
FROM oven/bun:1.4.0-alpine AS frontend-runner
WORKDIR /app
RUN apk update && apk add --no-cache curl && rm -rf /var/cache/apk/*
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 nextjs
COPY --from=frontend-builder /app/public ./public
RUN mkdir .next && chown nextjs:nodejs .next
# Leverage output traces to reduce image size
COPY --from=frontend-builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=frontend-builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# Copy server wrapper for runtime environment variable injection
COPY --chown=nextjs:nodejs apps/web/server-wrapper.js ./
RUN chmod +x server-wrapper.js
# ───────────────────────────────────────────────
# Stage 4: Collab server build
# ───────────────────────────────────────────────
FROM oven/bun:1.4.0-alpine AS collab-builder
WORKDIR /app
COPY apps/collab/package.json apps/collab/bun.lock* ./
RUN bun install --frozen-lockfile
COPY apps/collab/tsconfig.json ./
COPY apps/collab/src/ ./src/
RUN bun run build
# ───────────────────────────────────────────────
# Stage 5: Final image combining frontend + backend + collab
# ───────────────────────────────────────────────
FROM python:3.14.6-slim-bookworm AS runner
# Single apt layer: nginx, curl, netcat, node, pm2
RUN apt-get update \
&& apt-get install -y --no-install-recommends nginx curl netcat-openbsd ca-certificates gnupg unzip build-essential \
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& npm install -g pm2 \
&& curl -fsSL https://bun.sh/install | bash \
&& apt-get purge -y gnupg \
&& apt-get autoremove -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /root/.npm \
&& rm /etc/nginx/sites-enabled/default
ENV PATH="/root/.bun/bin:${PATH}"
# Copy the frontend standalone build
COPY --from=frontend-runner /app /app/web
# Backend: install deps first (better layer caching)
WORKDIR /app/api
COPY ./apps/api/uv.lock ./apps/api/pyproject.toml ./
RUN pip install --no-cache-dir --upgrade pip uv \
&& uv sync --no-dev
COPY ./apps/api ./
# Remove Enterprise Edition folder for public builds
ARG LEARNHOUSE_PUBLIC=false
RUN if [ "$LEARNHOUSE_PUBLIC" = "true" ]; then rm -rf /app/api/ee; fi
# Collab server: copy built JS + production deps
WORKDIR /app/collab
COPY --from=collab-builder /app/dist ./dist
COPY apps/collab/package.json apps/collab/bun.lock* ./
RUN bun install --production
# Copy configs and scripts
WORKDIR /app
COPY ./docker/nginx.conf /etc/nginx/conf.d/default.conf
COPY ./apps/api/docker-entrypoint.sh /app/api/docker-entrypoint.sh
COPY ./docker/start.sh /app/start.sh
RUN chmod +x /app/api/docker-entrypoint.sh /app/start.sh
# PYTHONDONTWRITEBYTECODE: the image ships read-only source and gains nothing
# from writing .pyc files back into it. It also keeps __pycache__ out of the
# enterprise tree, where stale bytecode could otherwise shadow a source file
# that verifies clean against the signed manifest.
ENV PORT=8000 LEARNHOUSE_PORT=9000 COLLAB_PORT=4000 HOSTNAME=0.0.0.0 LEARNHOUSE_OSS=true NEXT_PUBLIC_LEARNHOUSE_OSS=true PYTHONDONTWRITEBYTECODE=1
EXPOSE 80 9000 4000
CMD ["sh", "/app/start.sh"]