Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 45 additions & 21 deletions apps/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,40 +1,64 @@
# Build stage
# syntax=docker/dockerfile:1.4
# NOTE: This Dockerfile requires Docker BuildKit (default since Docker 23.0)
# For older Docker versions, build with: DOCKER_BUILDKIT=1 docker build ...
# Or use: docker buildx build ...

################################################################################
# CACHE OPTIMIZATION STRATEGY:
# 1. turbo prune: Automatically extracts only needed packages (no manual COPY!)
# 2. pnpm fetch: Downloads packages using ONLY lockfile (most cacheable)
# 3. pnpm install --offline: Instant since packages already fetched
# 4. Prisma generate: Separate layer, changes rarely
# 5. Build with turbo cache: Incremental builds via cache mount
################################################################################

# Stage 1: Pruner - extracts only the packages needed for @refly/api
FROM node:20.19.1-alpine3.20 AS pruner
RUN npm install -g turbo
WORKDIR /app
COPY . .
RUN turbo prune @refly/api --docker

# Stage 2: Builder - installs dependencies and builds
FROM node:20.19.1-alpine3.20 AS builder
WORKDIR /app

# Install pnpm globally
RUN npm install -g pnpm

# Set environment variables to skip gyp-related installations
# Set environment variables
ENV npm_config_gyp_ignore=true
ENV CYPRESS_INSTALL_BINARY=0

# Set node options to increase memory limit
ENV NODE_OPTIONS='--max_old_space_size=8192'

# Copy all necessary files in one layer
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json turbo.json ./
COPY apps/api/package.json ./apps/api/
COPY apps/api/prisma ./apps/api/prisma
COPY packages/ ./packages/
# Step 1: Fetch dependencies using ONLY the pruned lockfile
COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
pnpm fetch

# Install dependencies with workspace support
RUN pnpm install --ignore-scripts
# Step 2: Copy pruned package.json files (auto-generated, no manual list!)
COPY --from=pruner /app/out/json/ .

# Copy remaining source code
COPY . .
# Step 3: Install from cache (--offline makes this instant)
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
pnpm install --offline --ignore-scripts

# Build packages in correct order
RUN pnpm build:api
# Step 4: Copy full source code (pruned to only what's needed)
COPY --from=pruner /app/out/full/ .

# Step 5: Copy prisma schema and generate client
COPY apps/api/prisma ./apps/api/prisma
RUN cd apps/api && pnpm exec prisma generate
Comment on lines +46 to +51
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove the redundant COPY of the prisma directory.

Line 50 copies apps/api/prisma, but this is already included in the pruned source copied on line 47. Since turbo prune outputs "the full source code of all internal packages needed to build the target" along with a pruned lockfile, the prisma schema is already present. The separate COPY is redundant and causes unnecessary Docker cache invalidation when prisma files change. Delete line 50 and adjust line 51 accordingly, or consolidate the operations.

🤖 Prompt for AI Agents
In apps/api/Dockerfile around lines 46 to 51, remove the redundant "COPY
apps/api/prisma ./apps/api/prisma" since the pruned full source copied on line
47 already includes the prisma schema; delete that COPY and adjust the following
RUN line to run "cd apps/api && pnpm exec prisma generate" immediately after the
full-source COPY (or consolidate into a single RUN if you prefer), ensuring no
extra COPY is left that would invalidate the Docker cache when prisma files
change.


# # Clean up development dependencies
# RUN rm -rf node_modules
# RUN pnpm install --prod --frozen-lockfile --ignore-scripts
# Step 6: Build with turbo cache mount
COPY turbo.json ./
RUN --mount=type=cache,id=turbo,target=/app/.turbo \
pnpm build:api

# wkhtmltopdf stage
# Stage 3: wkhtmltopdf binary
FROM surnet/alpine-wkhtmltopdf:3.20.3-0.12.6-small AS wkhtmltopdf

# Production stage
# Stage 4: Production
FROM node:20.19.1-alpine3.20 AS production
WORKDIR /app

Expand Down Expand Up @@ -90,4 +114,4 @@ WORKDIR /app/apps/api/dist

EXPOSE 3000

CMD ["node", "-r", "./scripts/preload.js", "main.js"]
CMD ["node", "-r", "./scripts/preload.js", "main.js"]
Loading