info
This documentation is automatically synchronized from the claude-hub repository. Last updated: 2025-06-01
Docker Build Optimization Guide
This document describes the optimizations implemented in our Docker CI/CD pipeline for faster builds and better caching.
Overview
Our optimized Docker build pipeline includes:
- Self-hosted runner support with automatic fallback
- Multi-stage builds for efficient layering
- Advanced caching strategies
- Container-based testing
- Parallel builds for multiple images
- Security scanning integration
Self-Hosted Runners
Configuration
- Labels:
self-hosted, linux, x64, docker
- Usage: All Docker builds use self-hosted runners by default for improved performance
- Local Cache: Self-hosted runners maintain Docker layer cache between builds
- Fallback: Configurable via
USE_SELF_HOSTED
repository variable
Runner Setup
Self-hosted runners provide:
- Persistent Docker layer cache
- Faster builds (no image pull overhead)
- Better network throughput for pushing images
- Cost savings on GitHub Actions minutes
Fallback Strategy
The workflow implements a flexible fallback mechanism:
- Default behavior: Uses self-hosted runners (
self-hosted, linux, x64, docker
) - Override option: Set repository variable
USE_SELF_HOSTED=false
to force GitHub-hosted runners - Timeout protection: 30-minute timeout prevents hanging on unavailable runners
- Failure detection:
build-fallback
job provides instructions if self-hosted runners fail
To manually switch to GitHub-hosted runners:
# Via GitHub UI: Settings → Secrets and variables → Actions → Variables
# Add: USE_SELF_HOSTED = false
# Or via GitHub CLI:
gh variable set USE_SELF_HOSTED --body "false"
The runner selection logic:
runs-on: ${{ fromJSON(format('["{0}"]', (vars.USE_SELF_HOSTED == 'false' && 'ubuntu-latest' || 'self-hosted, linux, x64, docker'))) }}
Multi-Stage Dockerfile
Our Dockerfile uses multiple stages for optimal caching and smaller images:
- Builder Stage: Compiles TypeScript
- Prod-deps Stage: Installs production dependencies only
- Test Stage: Includes dev dependencies and test files
- Production Stage: Minimal runtime image
Benefits
- Parallel builds of independent stages
- Smaller final image (no build tools or dev dependencies)
- Test stage can run in CI without affecting production image
- Better layer caching between builds
Caching Strategies
1. GitHub Actions Cache (GHA)
cache-from: type=gha,scope=${{ matrix.image }}-prod
cache-to: type=gha,mode=max,scope=${{ matrix.image }}-prod
2. Registry Cache
cache-from: type=registry,ref=${{ org }}/claude-hub:nightly
3. Inline Cache
build-args: BUILDKIT_INLINE_CACHE=1
outputs: type=inline
4. Layer Ordering
- Package files copied first (changes less frequently)
- Source code copied after dependencies
- Build artifacts cached between stages
Container-Based Testing
Tests run inside Docker containers for:
- Consistent environment
- Parallel test execution
- Isolation from host system
- Same environment as production
Test Execution
# Unit tests in container
docker run --rm claude-hub:test npm test
# Integration tests with docker-compose
docker-compose -f docker-compose.test.yml run integration-test
# E2E tests against running services
docker-compose -f docker-compose.test.yml run e2e-test
Build Performance Optimizations
1. BuildKit Features
DOCKER_BUILDKIT=1
for improved performance--mount=type=cache
for package manager caches- Parallel stage execution
2. Docker Buildx
- Multi-platform builds (amd64, arm64)
- Advanced caching backends
- Build-only stages that don't ship to production
3. Context Optimization
.dockerignore
excludes unnecessary files- Minimal context sent to Docker daemon
- Faster uploads and builds
4. Dependency Caching
- Separate stage for production dependencies
- npm ci with --omit=dev for smaller images
- Cache mount for npm packages
Workflow Features
PR Builds
- Build and test without publishing
- Single platform (amd64) for speed
- Container-based test execution
- Security scanning with Trivy
Main Branch Builds
- Multi-platform builds (amd64, arm64)
- Push to registry with :nightly tag
- Update cache images
- Full test suite execution
Version Tag Builds
- Semantic versioning tags
- :latest tag update
- Multi-platform support
- Production-ready images
Security Scanning
Integrated Scanners
- Trivy: Vulnerability scanning for Docker images
- Hadolint: Dockerfile linting
- npm audit: Dependency vulnerability checks
- SARIF uploads: Results visible in GitHub Security tab
Monitoring and Metrics
Build Performance
- Build time per stage
- Cache hit rates
- Image size tracking
- Test execution time
Health Checks
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3002/health"]
interval: 30s
timeout: 10s
retries: 3
Local Development
Building locally
# Build with BuildKit
DOCKER_BUILDKIT=1 docker build -t claude-hub:local .
# Build specific stage
docker build --target test -t claude-hub:test .
# Run tests locally
docker-compose -f docker-compose.test.yml run test
Cache Management
# Clear builder cache
docker builder prune
# Use local cache
docker build --cache-from claude-hub:local .
Best Practices
- Order Dockerfile commands from least to most frequently changing
- Use specific versions for base images and dependencies
- Minimize layers by combining RUN commands
- Clean up package manager caches in the same layer
- Use multi-stage builds to reduce final image size
- Leverage BuildKit features for better performance
- Test in containers for consistency across environments
- Monitor build times and optimize bottlenecks
Troubleshooting
Slow Builds
- Check cache hit rates in build logs
- Verify .dockerignore is excluding large files
- Use
--progress=plain
to see detailed timings - Consider parallelizing independent stages
Cache Misses
- Ensure consistent base image versions
- Check for unnecessary file changes triggering rebuilds
- Use cache mounts for package managers
- Verify registry cache is accessible
Test Failures in Container
- Check environment variable differences
- Verify volume mounts are correct
- Ensure test dependencies are in test stage
- Check for hardcoded paths or ports