WIP! A BB-style forum, on the ATmosphere!
We're still working... we'll be back soon when we have something to show off!
node
typescript
hono
htmx
atproto
1# Stage 1: Build
2FROM node:22.12-alpine3.21 AS builder
3
4# Install build dependencies (bash needed for lexicon glob expansion)
5RUN apk add --no-cache bash
6
7# Install pnpm
8RUN npm install -g pnpm@9.15.4
9
10# Set working directory
11WORKDIR /build
12
13# Copy package files for dependency installation
14COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
15COPY apps/appview/package.json ./apps/appview/
16COPY apps/web/package.json ./apps/web/
17COPY packages/db/package.json ./packages/db/
18COPY packages/lexicon/package.json ./packages/lexicon/
19
20# Install all dependencies (including dev dependencies for build)
21# Skip prepare script (lefthook requires git, which we don't need in Docker)
22RUN pnpm install --frozen-lockfile --ignore-scripts
23
24# Copy source code (.dockerignore filters out unwanted files)
25COPY . .
26
27# Build all packages (turbo builds lexicon → appview + web)
28RUN pnpm build
29
30# Stage 2: Runtime
31FROM node:22.12-alpine3.21
32
33# Install nginx and wget (for health checks)
34RUN apk add --no-cache nginx wget
35
36# Set working directory
37WORKDIR /app
38
39# Copy package files for production install
40COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
41COPY apps/appview/package.json ./apps/appview/
42COPY apps/web/package.json ./apps/web/
43COPY packages/db/package.json ./packages/db/
44COPY packages/lexicon/package.json ./packages/lexicon/
45
46# Install pnpm and production dependencies only
47# Skip prepare script (lefthook not needed in production)
48RUN npm install -g pnpm@9.15.4 && \
49 pnpm install --prod --frozen-lockfile --ignore-scripts
50
51# Create non-root user and set permissions
52RUN addgroup -g 1001 -S atbb && \
53 adduser -S -D -H -u 1001 -h /app -s /sbin/nologin -G atbb atbb && \
54 chown -R atbb:atbb /app
55
56# Give nginx permissions to run as non-root
57RUN mkdir -p /var/lib/nginx /var/log/nginx /run/nginx && \
58 chown -R atbb:atbb /var/lib/nginx /var/log/nginx /run/nginx
59
60# Copy built artifacts from builder stage
61COPY --from=builder /build/apps/appview/dist ./apps/appview/dist
62COPY --from=builder /build/apps/web/dist ./apps/web/dist
63COPY --from=builder /build/packages/db/dist ./packages/db/dist
64COPY --from=builder /build/packages/lexicon/dist ./packages/lexicon/dist
65
66# Copy migration files for drizzle-kit
67COPY --from=builder /build/apps/appview/drizzle ./apps/appview/drizzle
68
69# Copy nginx config to standard location and entrypoint script
70COPY nginx.conf /etc/nginx/nginx.conf
71COPY entrypoint.sh ./
72RUN chmod +x entrypoint.sh
73
74# Expose port 80 (nginx listens here)
75EXPOSE 80
76
77# Add health check for container orchestration
78HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
79 CMD wget --no-verbose --tries=1 --spider http://localhost/api/healthz || exit 1
80
81# Switch to non-root user
82USER atbb
83
84# Set entrypoint
85ENTRYPOINT ["/app/entrypoint.sh"]