You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
4.7 KiB
Markdown
154 lines
4.7 KiB
Markdown
# Drone CI Pipeline Build Time Optimization
|
|
|
|
## Current Issues (6+ minutes to build)
|
|
|
|
### Time Breakdown from Logs:
|
|
1. **Docker daemon startup**: ~1.5 seconds
|
|
2. **`npm install next -g`**: ~1 minute 13 seconds ❌ (UNNECESSARY)
|
|
3. **`npm ci`**: ~2 minutes
|
|
4. **Image pulls**: ~30 seconds
|
|
5. **Build overhead**: Multiple intermediate containers
|
|
6. **No layer caching**: Every build starts from scratch
|
|
|
|
## Optimizations Implemented
|
|
|
|
### 1. **Remove Unnecessary `npm install next -g`** (Saves ~1-1.5 minutes)
|
|
- **Issue**: The current Dockerfile globally installs Next.js, which is already in package.json
|
|
- **Fix**: Removed this step entirely in the optimized Dockerfile
|
|
- **Savings**: ~70-80 seconds
|
|
|
|
### 2. **Multi-Stage Docker Build** (Saves ~30-60 seconds + smaller image)
|
|
- **Issue**: Single-stage build includes build dependencies in final image
|
|
- **Fix**:
|
|
- Stage 1 (deps): Install dependencies
|
|
- Stage 2 (builder): Build application
|
|
- Stage 3 (runner): Minimal runtime image
|
|
- **Benefits**:
|
|
- Smaller final image (only production dependencies)
|
|
- Better layer caching
|
|
- Faster subsequent builds
|
|
|
|
### 3. **Enable Docker Layer Caching** (Saves ~2-3 minutes after first build)
|
|
- **Issue**: No caching between builds means npm packages reinstall every time
|
|
- **Fix**: Added `cache_from` in .drone.yml pointing to previous images
|
|
- **Benefits**:
|
|
- Dependencies cached if package.json unchanged
|
|
- Source code changes don't trigger dependency reinstall
|
|
- Build steps only run if inputs change
|
|
|
|
### 4. **Enable Docker BuildKit** (Saves ~10-30 seconds)
|
|
- **Issue**: Using legacy Docker builder
|
|
- **Fix**: Set `DOCKER_BUILDKIT=1` environment variable
|
|
- **Benefits**:
|
|
- Parallel build stages
|
|
- Better caching
|
|
- Faster builds
|
|
|
|
### 5. **Optimized Layer Order** (Maximizes cache hits)
|
|
- **Issue**: Copying all files before installing dependencies
|
|
- **Fix**: Copy package.json first, install deps, then copy source
|
|
- **Benefits**:
|
|
- Dependencies only reinstall when package files change
|
|
- Code changes don't invalidate dependency cache
|
|
|
|
## Expected Build Time Improvements
|
|
|
|
### First Build (Cold Cache):
|
|
- **Current**: ~6 minutes
|
|
- **Optimized**: ~4-4.5 minutes
|
|
- **Improvement**: ~25-30%
|
|
|
|
### Subsequent Builds (Warm Cache):
|
|
- **Current**: ~6 minutes (no caching)
|
|
- **Optimized with code changes only**: ~1.5-2 minutes
|
|
- **Optimized with dependency changes**: ~3-3.5 minutes
|
|
- **Improvement**: ~60-75% for typical code-only changes
|
|
|
|
## Implementation Steps
|
|
|
|
### Quick Win (Immediate ~1.5 min improvement):
|
|
|
|
1. Replace current Dockerfile:
|
|
```bash
|
|
mv docker/Dockerfile docker/Dockerfile.old
|
|
mv docker/Dockerfile.optimized docker/Dockerfile
|
|
```
|
|
|
|
### Full Optimization (Up to 75% improvement):
|
|
|
|
1. Replace Dockerfile (as above)
|
|
2. Replace .drone.yml with caching enabled:
|
|
```bash
|
|
mv .drone.yml .drone.yml.old
|
|
mv .drone.yml.optimized .drone.yml
|
|
```
|
|
|
|
3. Commit and push:
|
|
```bash
|
|
git add docker/Dockerfile .drone.yml
|
|
git commit -m "optimize: improve CI build time with multi-stage builds and layer caching"
|
|
git push
|
|
```
|
|
|
|
## Additional Optimization Options (Future)
|
|
|
|
### Option 1: Enable Next.js Standalone Output (Extra 20-30% improvement)
|
|
Add to `next.config.mjs`:
|
|
```javascript
|
|
const nextConfig = {
|
|
output: 'standalone',
|
|
eslint: {
|
|
ignoreDuringBuilds: true,
|
|
},
|
|
typescript: {
|
|
ignoreBuildErrors: true,
|
|
},
|
|
}
|
|
```
|
|
|
|
This creates a minimal production build with only required files.
|
|
|
|
### Option 2: Use npm Registry Mirror/Cache (Saves ~30-60 seconds)
|
|
Add to Dockerfile before `npm ci`:
|
|
```dockerfile
|
|
RUN npm config set registry https://your-npm-mirror.com
|
|
```
|
|
|
|
### Option 3: Pre-built Base Image (Saves ~1-2 minutes)
|
|
Create a custom base image with common dependencies pre-installed:
|
|
```dockerfile
|
|
FROM node:22-alpine
|
|
RUN apk add --no-cache python3 make g++
|
|
# Pre-install common dependencies
|
|
RUN npm install -g next@15.3.2
|
|
```
|
|
|
|
### Option 4: Parallel Testing (if applicable)
|
|
If you add testing steps, run them in parallel with builds using Drone's parallel step feature.
|
|
|
|
## Verification
|
|
|
|
After implementing, monitor build times in Drone CI dashboard:
|
|
|
|
1. **First build after changes**: Should be ~4-4.5 minutes
|
|
2. **Build with code-only changes**: Should be ~1.5-2 minutes
|
|
3. **Build with package.json changes**: Should be ~3-3.5 minutes
|
|
|
|
## Rollback Plan
|
|
|
|
If issues occur:
|
|
```bash
|
|
mv docker/Dockerfile.old docker/Dockerfile
|
|
mv .drone.yml.old .drone.yml
|
|
git add docker/Dockerfile .drone.yml
|
|
git commit -m "rollback: revert pipeline optimizations"
|
|
git push
|
|
```
|
|
|
|
## Notes
|
|
|
|
- BuildKit may not be available on older Docker versions (requires Docker 18.09+)
|
|
- Layer caching requires the registry to support it (most modern registries do)
|
|
- First build will still be slow as it populates the cache
|
|
- Consider scheduled cache warming builds if needed
|