Skip to content

perf(docker): use turbo prune for app.Dockerfile#4322

Merged
waleedlatif1 merged 2 commits intostagingfrom
waleedlatif1/app-dockerfile-turbo-prune
Apr 28, 2026
Merged

perf(docker): use turbo prune for app.Dockerfile#4322
waleedlatif1 merged 2 commits intostagingfrom
waleedlatif1/app-dockerfile-turbo-prune

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

@waleedlatif1 waleedlatif1 commented Apr 28, 2026

Summary

Refactors docker/app.Dockerfile to use turbo prune sim --docker instead of hand-maintaining a list of COPY packages/*/package.json lines. This matches the canonical Vercel/Turborepo monorepo Docker pattern and our existing realtime.Dockerfile.

Supersedes #4321 — that PR is a hotfix that adds a second `bun install` in the builder stage to recover devDependencies. This PR removes the need for that workaround entirely by installing the full dep set once in the `deps` stage against pruned manifests.

What changed

  • New `pruner` stage runs `turbo prune sim --docker`, emitting:
    • `out/json/` — pruned package manifests + `bun.lock` (cache key)
    • `out/full/` — only the sources sim transitively depends on
  • `deps` stage now copies from `out/json/` and runs a single `bun install` (no `--omit=dev` — tailwindcss/postcss are devDeps required at build time).
  • `builder` stage copies `node_modules` from deps + `out/full/` from pruner. Drops the global turbo install, manual workspace package.json copies, and individual config file copies.
  • Net: -59 / +24 lines, build cache only invalidates on real dep changes.

Why this is the right pattern

  • It's what Vercel's `with-docker` example and Turborepo's `with-docker` ship as the recommended monorepo Dockerfile shape.
  • Already in use in this repo via `docker/realtime.Dockerfile`.
  • Each workspace package becomes a content-addressable cache layer: edit `apps/sim/components/foo.tsx` and the deps stage cache stays warm.

Test plan

  • CI build (amd64) succeeds end-to-end
  • CI build (arm64, on main) succeeds end-to-end
  • Image runs and serves traffic
  • Verify build is reproducible — re-run with no source changes hits the deps cache layer

Replaces manual workspace package.json copies with `turbo prune sim --docker`,
matching the canonical Vercel/Turborepo monorepo pattern (and the existing
realtime.Dockerfile).

- New `pruner` stage emits `out/json` (manifests + lockfile) and `out/full`
  (sources) for only the packages sim actually depends on.
- `deps` stage installs from the pruned manifest, so cache invalidates only
  when package.json/bun.lock change — not on source edits.
- Drops 24 lines of brittle manual COPYs (one per workspace package).
- Single full install in deps (no --omit=dev) so build-time devDeps like
  tailwindcss/postcss are available — replaces the earlier hotfix that did
  a second install in the builder stage.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Apr 28, 2026 8:00pm

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented Apr 28, 2026

PR Summary

Medium Risk
Build pipeline changes can affect dependency resolution and Docker layer caching, potentially causing build failures or larger images if pruning/install assumptions are wrong. Runtime app logic is unchanged, but reviewers should validate the pruned workspace and devDependency inclusion are correct.

Overview
Switches the docker/app.Dockerfile build to the Turborepo Docker pattern by adding a pruner stage (turbo prune sim --docker) and using its outputs to drive the rest of the build.

The deps stage now installs from pruned out/json + bun.lock and includes devDependencies (needed for build-time tooling), while the builder stage copies the pruned source tree from out/full and removes the hand-maintained COPY lists and global turbo install.

Reviewed by Cursor Bugbot for commit 76851da. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 28, 2026

Greptile Summary

This PR replaces the hand-maintained COPY packages/*/package.json list in app.Dockerfile with a pruner stage that runs turbo prune sim --docker, matching the canonical Turborepo monorepo Docker pattern already used in realtime.Dockerfile. The change removes --omit=dev so build-time devDependencies (tailwindcss, postcss) are installed correctly, eliminating the need for the secondary bun install workaround in PR #4321. The .dockerignore is correctly configured to exclude .env*, node_modules, and out/, so the COPY . . in the pruner stage is safe.

Confidence Score: 5/5

This PR is safe to merge — the change is a clean adoption of the standard turbo prune pattern with no logic or security issues.

Single file changed, follows the established pattern already used in realtime.Dockerfile, turbo version is pinned, .dockerignore properly excludes sensitive files and node_modules, and the PR author reports successful CI builds on both amd64 and arm64. No P0 or P1 findings.

No files require special attention.

Important Files Changed

Filename Overview
docker/app.Dockerfile Refactors to canonical turbo prune --docker pattern: adds pruner stage with pinned turbo@2.9.6, simplifies deps/builder stages, removes manually-maintained package.json COPY list, and drops --omit=dev so devDependencies (tailwindcss, postcss) are correctly installed at build time.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    CTX[Build Context\n.dockerignore filters out\n.env*, node_modules, out/] --> BASE

    BASE[base\noven/bun:1.3.13-slim\n+ Node.js 22]

    BASE --> PRUNER[pruner\nbun install -g turbo@2.9.6\nCOPY . .\nturbo prune sim --docker]
    PRUNER --> |out/json/\npruned package.json files| DEPS
    PRUNER --> |out/bun.lock| DEPS
    PRUNER --> |out/full/\npruned source tree| BUILDER

    BASE --> DEPS[deps\nbun install --linker=hoisted\nno --omit=dev\nnode-gyp rebuild isolated-vm]
    DEPS --> |node_modules| BUILDER

    BASE --> BUILDER[builder\nbun run build\nturbo run build\nnext build]
    BUILDER --> |.next/standalone\n.next/static\npublic/| RUNNER

    BASE --> RUNNER[runner\nnon-root nextjs user\nbun apps/sim/server.js]
Loading

Reviews (2): Last reviewed commit: "chore(docker): pin turbo to 2.9.6 in pru..." | Re-trigger Greptile

Comment thread docker/app.Dockerfile Outdated
Match the version locked in package.json so pruner output is reproducible
across builds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 76851da. Configure here.

@waleedlatif1 waleedlatif1 merged commit dc20229 into staging Apr 28, 2026
14 checks passed
@waleedlatif1 waleedlatif1 deleted the waleedlatif1/app-dockerfile-turbo-prune branch April 28, 2026 20:06
waleedlatif1 added a commit that referenced this pull request Apr 28, 2026
* fix(docker): use full bun.lock and copy it into builder

The staging build for app.Dockerfile (commit dc20229, PR #4322) is
failing in two ways after switching to turbo prune:

1. turbo 2.9.6's pruned bun.lock is malformed for bun 1.3.x:
     error: Failed to resolve prod dependency 'wrap-ansi' for package
     'log-update' at bun.lock:2688:5
   Bun ignores it and falls back to a fresh resolve (~7m install).

2. Next.js 16.1.6's Turbopack production build can't infer the workspace
   root because /app/bun.lock doesn't exist in the builder stage:
     Error: We couldn't find the Next.js package (next/package.json)
     from the project directory: /app/apps/sim
   This blocks the build entirely.

Fix:
- deps stage: use the full bun.lock from /app/bun.lock (the original
  lockfile after `COPY . .` in pruner) instead of the broken
  /app/out/bun.lock that turbo prune emits.
- builder stage: also copy the full bun.lock to /app/bun.lock so
  Turbopack and turborepo can detect the workspace root.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(ci): bump deprecated Node.js 20 actions to Node.js 24 versions

GitHub Actions runners emit deprecation warnings for actions still on the
Node.js 20 runtime. Node.js 20 will be force-upgraded by GitHub on
2026-06-02 and removed on 2026-09-16.

Bumps to the latest stable major versions, all of which use Node.js 24:

- actions/cache: v4 -> v5
- actions/setup-node: v4 -> v6
- aws-actions/configure-aws-credentials: v4 -> v6
- docker/login-action: v3 -> v4

All require GHA runner v2.327.1+ which Blacksmith already runs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant