The prune command generates a partial monorepo for one target package: only the internal packages it needs, a pruned lockfile, and the root package.json. In a Docker build that means a smaller context and fewer installed dependencies, which reduces what you ship and what you must scan.
What it produces
According to the Turborepo reference, running prune for a package writes an output directory containing the full source of internal packages needed to build the target, a pruned lockfile with the subset needed for that target, and a copy of the root package.json.
turbo prune frontend
turbo prune frontend --docker
With the Docker option, the output is arranged for layer caching: a json folder with only the pruned workspace's package.json files, a full folder with source for the needed packages, and the pruned lockfile.
Why it helps security
| Benefit | Explanation |
|---|---|
| Smaller attack surface | Dependencies of unrelated apps are never installed in this image |
| Less to scan | The image inventory matches what the app needs |
| Stable layers | The dependency install layer changes only when the pruned manifests change |
| Clear scope | A reviewer can see which internal packages ship with an app |
A monorepo lockfile covers every app. Installing from it in each image drags along packages the image will never run. A pruned lockfile cuts that to the subset the target needs.
Settings worth knowing
- The production option excludes in workspace packages listed only in devDependencies when choosing what to include.
- By default, prune follows package dependencies, not task dependencies. A dependency listed only in a task relationship does not keep the package in the output unless a future flag for affected packages by task inputs is enabled.
- Files named by globalDependencies are not copied unless a separate future flag is on, so a root config file or .env may be missing from the pruned output.
- It respects gitignore by default.
A Dockerfile checklist
- Run prune with the Docker option in a builder stage.
- Copy only the json folder and pruned lockfile first, then install with a frozen lockfile so the install fails on drift.
- Copy the full folder after install, then build.
- Use a final stage that contains build output and production dependencies only.
- Pin base image versions by digest where you can.
- Scan the final image, not only the repository.
What prune does not do
It does not remove vulnerable packages that the target legitimately needs. It also does not decide which dependencies are reachable. It trims the tree by workspace relationships, so a finding in the pruned lockfile still needs triage.
Where Safeguard fits
Safeguard can inventory the dependencies your repository declares through SBOM and dependency scanning, and reachability analysis helps you decide which findings matter first. You can try a free scan on a repository to see what it finds. Check coverage for your specific build files before relying on it.
Try it yourself
Open the container image scan demo and look at how many packages a built image contains. A pruned build makes that list shorter.
Click through it at your own pace, or open it full screen.
Quick check
Does prune change my source code?
No. It copies a subset of the repository into an output directory and leaves the original untouched.
Is the pruned lockfile enough to install reproducibly?
It is a subset of your original lockfile, so installing with a frozen lockfile uses the same resolved versions. Check that your package manager's frozen mode is enabled.
Sources
Last reviewed: 19 October 2026.