Problem
Multiple applications deployed on the same server are each downloading dependencies independently, causing slow builds and wasted bandwidth.
Solutions Implemented
1. BuildKit Cache Mounts (HIGHEST IMPACT)
Enable Docker BuildKit and use cache mounts to share package caches across all builds on the same server.
For Next.js/React Apps (pnpm):
# In build stage, replace:RUN pnpm install
# With:RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile
For .NET Apps:
# In build stage, replace:RUN dotnet restore
# With:RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
dotnet restore
2. Jenkins Pipeline Configuration
Update your Jenkinsfile to enable BuildKit:
pipeline {
agent any
environment {
DOCKER_BUILDKIT = '1'
}
stages {
stage('Build') {
steps {
sh 'docker build --build-arg BUILDKIT_INLINE_CACHE=1 -t myapp .'
}
}
}
}
3. Docker Daemon Configuration
On your server, edit /etc/docker/daemon.json :
{"features": {
"buildkit": true}}
Restart Docker:
sudo systemctl restart docker
4. Multi-Stage Build Best Practices
✅ Your Dockerfiles already use multi-stage builds
✅ Dependencies are copied before source code
5. Layer Caching Order (Verify)
Ensure this order in all Dockerfiles:
Install package manager (pnpm/dotnet)
Copy package files only (package.json, pnpm-lock.yaml, *.csproj)
Install dependencies (with cache mount)
Copy source code
Build application
Expected Performance Improvements
| Optimization | First Build | Subsequent Builds | Benefit |
|---|
| Cache Mounts | Same | 60-90% faster | Shares npm/pnpm/NuGet cache |
| Layer Caching | Same | 40-70% faster | Reuses unchanged layers |
| Combined | Same | 70-95% faster | Maximum efficiency |
Quick Application Guide
Next.js Apps (pnpm-based):
Optimization Pattern:
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile
Vite/React Apps (pnpm-based):
Same optimization as Next.js
.NET Apps:
Optimization Pattern:
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
dotnet restore
Implementation Steps
Enable BuildKit (server-level - do this first):
echo '{"features": {"buildkit": true}}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
Update Jenkinsfiles (add to environment):
environment {
DOCKER_BUILDKIT = '1'
}
Update Dockerfiles (for each app):
Verify Build Logs :
Additional Optimizations
A. Use .dockerignore
Create .dockerignore in each project:
node_modules
.next
.git
*.log
.env.local
dist
build
B. Prune Unused Images Regularly
Add Jenkins job:
stage('Cleanup') {
steps {
sh 'docker system prune -af --filter "until=168h"'
}
}
C. Use Registry Cache (Advanced)
For even faster builds, push cache to Docker registry:
docker build \
--cache-from myregistry/app:cache \
--build-arg BUILDKIT_INLINE_CACHE=1 \
-t myregistry/app:latest \
--push .
Monitoring Success
After implementation, track:
Build duration (should decrease by 60-90%)
Network bandwidth usage (should decrease significantly)
Disk space usage (cache mounts use more space but worth it)
Run this to see cache usage:
docker system df -v