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

# 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