mirror of
https://github.com/wshobson/agents.git
synced 2026-03-18 09:37:15 +00:00
Repository Restructure: - Move all 83 agent .md files to agents/ subdirectory - Add 15 workflow orchestrators from commands repo to workflows/ - Add 42 development tools from commands repo to tools/ - Update README for unified repository structure This prepares the repository for unified plugin marketplace integration. The commands repository functionality is now fully integrated, providing complete workflow orchestration and development tooling alongside agents. Directory Structure: - agents/ - 83 specialized AI agents - workflows/ - 15 multi-agent orchestration commands - tools/ - 42 focused development utilities No breaking changes to agent functionality - all agents remain accessible with same names and behavior. Adds workflow and tool commands for enhanced multi-agent coordination capabilities.
2338 lines
73 KiB
Markdown
2338 lines
73 KiB
Markdown
---
|
|
model: claude-sonnet-4-0
|
|
---
|
|
|
|
# Docker Optimization
|
|
|
|
You are a Docker optimization expert specializing in creating efficient, secure, and minimal container images. Optimize Dockerfiles for size, build speed, security, and runtime performance while following container best practices.
|
|
|
|
## Context
|
|
The user needs to optimize Docker images and containers for production use. Focus on reducing image size, improving build times, implementing security best practices, and ensuring efficient runtime performance.
|
|
|
|
## Requirements
|
|
$ARGUMENTS
|
|
|
|
## Instructions
|
|
|
|
### 1. Container Optimization Strategy Selection
|
|
|
|
Choose the right optimization approach based on your application type and requirements:
|
|
|
|
**Optimization Strategy Matrix**
|
|
```python
|
|
from typing import Dict, List, Any, Optional
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
import docker
|
|
import json
|
|
import subprocess
|
|
import tempfile
|
|
|
|
@dataclass
|
|
class OptimizationRecommendation:
|
|
category: str
|
|
priority: str
|
|
impact: str
|
|
effort: str
|
|
description: str
|
|
implementation: str
|
|
validation: str
|
|
|
|
class SmartDockerOptimizer:
|
|
def __init__(self):
|
|
self.client = docker.from_env()
|
|
self.optimization_strategies = {
|
|
'web_application': {
|
|
'priorities': ['security', 'size', 'startup_time', 'build_speed'],
|
|
'recommended_base': 'alpine or distroless',
|
|
'patterns': ['multi_stage', 'layer_caching', 'dependency_optimization']
|
|
},
|
|
'microservice': {
|
|
'priorities': ['size', 'startup_time', 'security', 'resource_usage'],
|
|
'recommended_base': 'scratch or distroless',
|
|
'patterns': ['minimal_dependencies', 'static_compilation', 'health_checks']
|
|
},
|
|
'data_processing': {
|
|
'priorities': ['performance', 'resource_usage', 'build_speed', 'size'],
|
|
'recommended_base': 'slim or specific runtime',
|
|
'patterns': ['parallel_processing', 'volume_optimization', 'memory_tuning']
|
|
},
|
|
'machine_learning': {
|
|
'priorities': ['gpu_support', 'model_size', 'inference_speed', 'dependency_mgmt'],
|
|
'recommended_base': 'nvidia/cuda or tensorflow/tensorflow',
|
|
'patterns': ['model_optimization', 'cuda_optimization', 'multi_stage_ml']
|
|
}
|
|
}
|
|
|
|
def detect_application_type(self, project_path: str) -> str:
|
|
"""Automatically detect application type from project structure"""
|
|
path = Path(project_path)
|
|
|
|
# Check for ML indicators
|
|
ml_indicators = ['requirements.txt', 'environment.yml', 'model.pkl', 'model.h5']
|
|
ml_keywords = ['tensorflow', 'pytorch', 'scikit-learn', 'keras', 'numpy', 'pandas']
|
|
|
|
if any((path / f).exists() for f in ml_indicators):
|
|
if (path / 'requirements.txt').exists():
|
|
with open(path / 'requirements.txt') as f:
|
|
content = f.read().lower()
|
|
if any(keyword in content for keyword in ml_keywords):
|
|
return 'machine_learning'
|
|
|
|
# Check for microservice indicators
|
|
if any(f.name in ['go.mod', 'main.go', 'cmd'] for f in path.iterdir()):
|
|
return 'microservice'
|
|
|
|
# Check for data processing
|
|
data_indicators = ['airflow', 'kafka', 'spark', 'hadoop']
|
|
if any((path / f).exists() for f in ['docker-compose.yml', 'k8s']):
|
|
return 'data_processing'
|
|
|
|
# Default to web application
|
|
return 'web_application'
|
|
|
|
def analyze_dockerfile_comprehensively(self, dockerfile_path: str, project_path: str) -> Dict[str, Any]:
|
|
"""
|
|
Comprehensive Dockerfile analysis with modern optimization recommendations
|
|
"""
|
|
app_type = self.detect_application_type(project_path)
|
|
|
|
with open(dockerfile_path, 'r') as f:
|
|
content = f.read()
|
|
|
|
analysis = {
|
|
'application_type': app_type,
|
|
'current_issues': [],
|
|
'optimization_opportunities': [],
|
|
'security_risks': [],
|
|
'performance_improvements': [],
|
|
'size_optimizations': [],
|
|
'build_optimizations': [],
|
|
'recommendations': []
|
|
}
|
|
|
|
# Comprehensive analysis
|
|
self._analyze_base_image_strategy(content, analysis)
|
|
self._analyze_layer_efficiency(content, analysis)
|
|
self._analyze_security_posture(content, analysis)
|
|
self._analyze_build_performance(content, analysis)
|
|
self._analyze_runtime_optimization(content, analysis)
|
|
self._generate_strategic_recommendations(analysis, app_type)
|
|
|
|
return analysis
|
|
|
|
def _analyze_base_image_strategy(self, content: str, analysis: Dict):
|
|
"""Analyze base image selection and optimization opportunities"""
|
|
base_image_patterns = {
|
|
'outdated_versions': {
|
|
'pattern': r'FROM\s+([^:]+):(?!latest)([0-9]+\.[0-9]+)(?:\s|$)',
|
|
'severity': 'medium',
|
|
'recommendation': 'Consider updating to latest stable version'
|
|
},
|
|
'latest_tag': {
|
|
'pattern': r'FROM\s+([^:]+):latest',
|
|
'severity': 'high',
|
|
'recommendation': 'Pin to specific version for reproducible builds'
|
|
},
|
|
'large_base_images': {
|
|
'patterns': [
|
|
r'FROM\s+ubuntu(?!.*slim)',
|
|
r'FROM\s+centos',
|
|
r'FROM\s+debian(?!.*slim)',
|
|
r'FROM\s+node(?!.*alpine)'
|
|
],
|
|
'severity': 'medium',
|
|
'recommendation': 'Consider using smaller alternatives (alpine, slim, distroless)'
|
|
},
|
|
'missing_multi_stage': {
|
|
'pattern': r'FROM\s+(?!.*AS\s+)',
|
|
'count_threshold': 1,
|
|
'severity': 'low',
|
|
'recommendation': 'Consider multi-stage builds for smaller final images'
|
|
}
|
|
}
|
|
|
|
# Check for base image optimization opportunities
|
|
for issue_type, config in base_image_patterns.items():
|
|
if 'patterns' in config:
|
|
for pattern in config['patterns']:
|
|
if re.search(pattern, content, re.IGNORECASE):
|
|
analysis['size_optimizations'].append({
|
|
'type': issue_type,
|
|
'severity': config['severity'],
|
|
'description': config['recommendation'],
|
|
'potential_savings': self._estimate_size_savings(issue_type)
|
|
})
|
|
elif 'pattern' in config:
|
|
matches = re.findall(config['pattern'], content, re.IGNORECASE)
|
|
if matches:
|
|
analysis['current_issues'].append({
|
|
'type': issue_type,
|
|
'severity': config['severity'],
|
|
'instances': len(matches),
|
|
'description': config['recommendation']
|
|
})
|
|
|
|
def _analyze_layer_efficiency(self, content: str, analysis: Dict):
|
|
"""Analyze Docker layer efficiency and caching opportunities"""
|
|
lines = content.split('\n')
|
|
run_commands = [line for line in lines if line.strip().startswith('RUN')]
|
|
|
|
# Multiple RUN commands analysis
|
|
if len(run_commands) > 3:
|
|
analysis['build_optimizations'].append({
|
|
'type': 'excessive_layers',
|
|
'severity': 'medium',
|
|
'current_count': len(run_commands),
|
|
'recommended_count': '1-3',
|
|
'description': f'Found {len(run_commands)} RUN commands. Consider combining related operations.',
|
|
'implementation': 'Combine RUN commands with && to reduce layers'
|
|
})
|
|
|
|
# Package manager cleanup analysis
|
|
package_managers = {
|
|
'apt': {'install': r'apt-get\s+install', 'cleanup': r'rm\s+-rf\s+/var/lib/apt/lists'},
|
|
'yum': {'install': r'yum\s+install', 'cleanup': r'yum\s+clean\s+all'},
|
|
'apk': {'install': r'apk\s+add', 'cleanup': r'rm\s+-rf\s+/var/cache/apk'}
|
|
}
|
|
|
|
for pm_name, patterns in package_managers.items():
|
|
if re.search(patterns['install'], content) and not re.search(patterns['cleanup'], content):
|
|
analysis['size_optimizations'].append({
|
|
'type': f'{pm_name}_cleanup_missing',
|
|
'severity': 'medium',
|
|
'description': f'Missing {pm_name} cache cleanup',
|
|
'potential_savings': '50-200MB',
|
|
'implementation': f'Add cleanup command in same RUN layer'
|
|
})
|
|
|
|
# Copy optimization analysis
|
|
copy_commands = [line for line in lines if line.strip().startswith(('COPY', 'ADD'))]
|
|
if any('.' in cmd for cmd in copy_commands):
|
|
analysis['build_optimizations'].append({
|
|
'type': 'inefficient_copy',
|
|
'severity': 'low',
|
|
'description': 'Consider using .dockerignore and specific COPY commands',
|
|
'implementation': 'Copy only necessary files to improve build cache efficiency'
|
|
})
|
|
|
|
def _generate_strategic_recommendations(self, analysis: Dict, app_type: str):
|
|
"""Generate strategic optimization recommendations based on application type"""
|
|
strategy = self.optimization_strategies[app_type]
|
|
|
|
# Priority-based recommendations
|
|
for priority in strategy['priorities']:
|
|
if priority == 'security':
|
|
analysis['recommendations'].append(OptimizationRecommendation(
|
|
category='Security',
|
|
priority='High',
|
|
impact='Critical',
|
|
effort='Medium',
|
|
description='Implement security scanning and hardening',
|
|
implementation=self._get_security_implementation(app_type),
|
|
validation='Run Trivy and Hadolint scans'
|
|
))
|
|
elif priority == 'size':
|
|
analysis['recommendations'].append(OptimizationRecommendation(
|
|
category='Size Optimization',
|
|
priority='High',
|
|
impact='High',
|
|
effort='Low',
|
|
description=f'Use {strategy["recommended_base"]} base image',
|
|
implementation=self._get_size_implementation(app_type),
|
|
validation='Compare image sizes before/after'
|
|
))
|
|
elif priority == 'startup_time':
|
|
analysis['recommendations'].append(OptimizationRecommendation(
|
|
category='Startup Performance',
|
|
priority='Medium',
|
|
impact='High',
|
|
effort='Medium',
|
|
description='Optimize application startup time',
|
|
implementation=self._get_startup_implementation(app_type),
|
|
validation='Measure container startup time'
|
|
))
|
|
|
|
def _estimate_size_savings(self, optimization_type: str) -> str:
|
|
"""Estimate potential size savings for optimization"""
|
|
savings_map = {
|
|
'large_base_images': '200-800MB',
|
|
'apt_cleanup_missing': '50-200MB',
|
|
'yum_cleanup_missing': '100-300MB',
|
|
'apk_cleanup_missing': '20-100MB',
|
|
'excessive_layers': '10-50MB',
|
|
'multi_stage_optimization': '100-500MB'
|
|
}
|
|
return savings_map.get(optimization_type, '10-50MB')
|
|
|
|
def _get_security_implementation(self, app_type: str) -> str:
|
|
"""Get security implementation based on app type"""
|
|
implementations = {
|
|
'web_application': 'Non-root user, security scanning, minimal packages',
|
|
'microservice': 'Distroless base, static compilation, capability dropping',
|
|
'data_processing': 'Secure data handling, encrypted volumes, network policies',
|
|
'machine_learning': 'Model encryption, secure model serving, GPU security'
|
|
}
|
|
return implementations.get(app_type, 'Standard security hardening')
|
|
```
|
|
|
|
**Advanced Multi-Framework Dockerfile Generator**
|
|
```python
|
|
class FrameworkOptimizedDockerfileGenerator:
|
|
def __init__(self):
|
|
self.templates = {
|
|
'node_express': self._generate_node_express_optimized,
|
|
'python_fastapi': self._generate_python_fastapi_optimized,
|
|
'python_django': self._generate_python_django_optimized,
|
|
'golang_gin': self._generate_golang_optimized,
|
|
'java_spring': self._generate_java_spring_optimized,
|
|
'rust_actix': self._generate_rust_optimized,
|
|
'dotnet_core': self._generate_dotnet_optimized
|
|
}
|
|
|
|
def generate_optimized_dockerfile(self, framework: str, config: Dict[str, Any]) -> str:
|
|
"""Generate highly optimized Dockerfile for specific framework"""
|
|
if framework not in self.templates:
|
|
raise ValueError(f"Unsupported framework: {framework}")
|
|
|
|
return self.templates[framework](config)
|
|
|
|
def _generate_node_express_optimized(self, config: Dict) -> str:
|
|
"""Generate optimized Node.js Express Dockerfile"""
|
|
node_version = config.get('node_version', '20')
|
|
use_bun = config.get('use_bun', False)
|
|
|
|
if use_bun:
|
|
return f"""
|
|
# Optimized Node.js with Bun - Ultra-fast builds and runtime
|
|
FROM oven/bun:{config.get('bun_version', 'latest')} AS base
|
|
|
|
# Install dependencies (bun is much faster than npm)
|
|
WORKDIR /app
|
|
COPY package.json bun.lockb* ./
|
|
RUN bun install --frozen-lockfile --production
|
|
|
|
# Build stage
|
|
FROM base AS build
|
|
COPY . .
|
|
RUN bun run build
|
|
|
|
# Production stage
|
|
FROM gcr.io/distroless/nodejs{node_version}-debian11
|
|
WORKDIR /app
|
|
|
|
# Copy built application
|
|
COPY --from=build --chown=nonroot:nonroot /app/dist ./dist
|
|
COPY --from=build --chown=nonroot:nonroot /app/node_modules ./node_modules
|
|
COPY --from=build --chown=nonroot:nonroot /app/package.json ./
|
|
|
|
# Security: Run as non-root
|
|
USER nonroot
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
|
|
CMD ["node", "-e", "require('http').get('http://localhost:3000/health', (res) => process.exit(res.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"]
|
|
|
|
EXPOSE 3000
|
|
CMD ["node", "dist/index.js"]
|
|
"""
|
|
|
|
return f"""
|
|
# Optimized Node.js Express - Production-ready multi-stage build
|
|
FROM node:{node_version}-alpine AS deps
|
|
|
|
# Install dumb-init for proper signal handling
|
|
RUN apk add --no-cache dumb-init
|
|
|
|
# Create app directory with proper permissions
|
|
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
|
|
WORKDIR /app
|
|
USER nodejs
|
|
|
|
# Copy package files and install dependencies
|
|
COPY --chown=nodejs:nodejs package*.json ./
|
|
RUN npm ci --only=production --no-audit --no-fund && npm cache clean --force
|
|
|
|
# Build stage
|
|
FROM node:{node_version}-alpine AS build
|
|
WORKDIR /app
|
|
COPY package*.json ./
|
|
RUN npm ci --no-audit --no-fund
|
|
COPY . .
|
|
RUN npm run build && npm run test
|
|
|
|
# Production stage
|
|
FROM node:{node_version}-alpine AS production
|
|
|
|
# Install dumb-init
|
|
RUN apk add --no-cache dumb-init
|
|
|
|
# Create user and app directory
|
|
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
|
|
WORKDIR /app
|
|
USER nodejs
|
|
|
|
# Copy built application
|
|
COPY --from=build --chown=nodejs:nodejs /app/dist ./dist
|
|
COPY --from=deps --chown=nodejs:nodejs /app/node_modules ./node_modules
|
|
COPY --from=build --chown=nodejs:nodejs /app/package.json ./
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
|
|
CMD node healthcheck.js || exit 1
|
|
|
|
# Expose port
|
|
EXPOSE 3000
|
|
|
|
# Use dumb-init for proper signal handling
|
|
ENTRYPOINT ["dumb-init", "--"]
|
|
CMD ["node", "dist/index.js"]
|
|
"""
|
|
|
|
def _generate_python_fastapi_optimized(self, config: Dict) -> str:
|
|
"""Generate optimized Python FastAPI Dockerfile"""
|
|
python_version = config.get('python_version', '3.11')
|
|
use_uv = config.get('use_uv', True)
|
|
|
|
if use_uv:
|
|
return f"""
|
|
# Ultra-fast Python with uv package manager
|
|
FROM python:{python_version}-slim AS base
|
|
|
|
# Install uv - the fastest Python package manager
|
|
RUN pip install uv
|
|
|
|
# Build dependencies
|
|
FROM base AS build
|
|
WORKDIR /app
|
|
|
|
# Copy requirements and install dependencies with uv
|
|
COPY requirements.txt ./
|
|
RUN uv venv /opt/venv && \\
|
|
. /opt/venv/bin/activate && \\
|
|
uv pip install --no-cache-dir -r requirements.txt
|
|
|
|
# Production stage
|
|
FROM python:{python_version}-slim AS production
|
|
|
|
# Install security updates
|
|
RUN apt-get update && apt-get upgrade -y && \\
|
|
apt-get install -y --no-install-recommends dumb-init && \\
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
# Create non-root user
|
|
RUN useradd -m -u 1001 appuser
|
|
WORKDIR /app
|
|
|
|
# Copy virtual environment
|
|
COPY --from=build /opt/venv /opt/venv
|
|
ENV PATH="/opt/venv/bin:$PATH"
|
|
|
|
# Copy application
|
|
COPY --chown=appuser:appuser . .
|
|
|
|
# Security: Run as non-root
|
|
USER appuser
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\
|
|
CMD python -c "import requests; requests.get('http://localhost:8000/health', timeout=5)"
|
|
|
|
EXPOSE 8000
|
|
|
|
# Use dumb-init and Gunicorn for production
|
|
ENTRYPOINT ["dumb-init", "--"]
|
|
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "--worker-class", "uvicorn.workers.UvicornWorker", "app.main:app"]
|
|
"""
|
|
|
|
# Standard optimized Python Dockerfile
|
|
return f"""
|
|
# Optimized Python FastAPI - Production-ready
|
|
FROM python:{python_version}-slim AS build
|
|
|
|
# Install build dependencies
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \\
|
|
build-essential \\
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Create virtual environment
|
|
RUN python -m venv /opt/venv
|
|
ENV PATH="/opt/venv/bin:$PATH"
|
|
|
|
# Install Python dependencies
|
|
COPY requirements.txt .
|
|
RUN pip install --no-cache-dir --upgrade pip && \\
|
|
pip install --no-cache-dir -r requirements.txt
|
|
|
|
# Production stage
|
|
FROM python:{python_version}-slim AS production
|
|
|
|
# Install runtime dependencies and security updates
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \\
|
|
dumb-init \\
|
|
&& apt-get upgrade -y \\
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Create non-root user
|
|
RUN useradd -m -u 1001 appuser
|
|
WORKDIR /app
|
|
|
|
# Copy virtual environment
|
|
COPY --from=build /opt/venv /opt/venv
|
|
ENV PATH="/opt/venv/bin:$PATH" \\
|
|
PYTHONUNBUFFERED=1 \\
|
|
PYTHONDONTWRITEBYTECODE=1 \\
|
|
PYTHONOPTIMIZE=2
|
|
|
|
# Copy application
|
|
COPY --chown=appuser:appuser . .
|
|
|
|
# Security: Run as non-root
|
|
USER appuser
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\
|
|
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)"
|
|
|
|
EXPOSE 8000
|
|
|
|
# Production server with proper signal handling
|
|
ENTRYPOINT ["dumb-init", "--"]
|
|
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "--worker-class", "uvicorn.workers.UvicornWorker", "app.main:app"]
|
|
"""
|
|
|
|
def _generate_golang_optimized(self, config: Dict) -> str:
|
|
"""Generate optimized Go Dockerfile with minimal final image"""
|
|
go_version = config.get('go_version', '1.21')
|
|
|
|
return f"""
|
|
# Optimized Go build - Ultra-minimal final image
|
|
FROM golang:{go_version}-alpine AS build
|
|
|
|
# Install git for go modules
|
|
RUN apk add --no-cache git ca-certificates tzdata
|
|
|
|
# Create build directory
|
|
WORKDIR /build
|
|
|
|
# Copy go mod files and download dependencies
|
|
COPY go.mod go.sum ./
|
|
RUN go mod download && go mod verify
|
|
|
|
# Copy source code
|
|
COPY . .
|
|
|
|
# Build static binary with optimizations
|
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \\
|
|
-ldflags='-w -s -extldflags "-static"' \\
|
|
-a -installsuffix cgo \\
|
|
-o app .
|
|
|
|
# Final stage - minimal scratch image
|
|
FROM scratch
|
|
|
|
# Copy necessary files from build stage
|
|
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
|
COPY --from=build /usr/share/zoneinfo /usr/share/zoneinfo
|
|
COPY --from=build /build/app /app
|
|
|
|
# Health check (using the app itself)
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
|
|
CMD ["/app", "--health-check"]
|
|
|
|
EXPOSE 8080
|
|
|
|
# Run the binary
|
|
ENTRYPOINT ["/app"]
|
|
"""
|
|
|
|
def _check_base_image(self, content, analysis):
|
|
"""Enhanced base image optimization analysis"""
|
|
from_match = re.search(r'^FROM\s+(.+?)(?:\s+AS\s+\w+)?$', content, re.MULTILINE)
|
|
if from_match:
|
|
base_image = from_match.group(1)
|
|
|
|
# Check for latest tag
|
|
if ':latest' in base_image or not ':' in base_image:
|
|
analysis['security_risks'].append({
|
|
'issue': 'Using latest or no tag',
|
|
'severity': 'HIGH',
|
|
'fix': 'Pin to specific version',
|
|
'example': f'FROM {base_image.split(":")[0]}:1.2.3',
|
|
'impact': 'Unpredictable builds, security vulnerabilities'
|
|
})
|
|
|
|
# Enhanced base image recommendations
|
|
optimization_recommendations = {
|
|
'ubuntu': {
|
|
'alternatives': ['ubuntu:22.04-slim', 'debian:bullseye-slim', 'alpine:3.18'],
|
|
'savings': '400-600MB',
|
|
'notes': 'Consider distroless for production'
|
|
},
|
|
'debian': {
|
|
'alternatives': ['debian:bullseye-slim', 'alpine:3.18', 'gcr.io/distroless/base'],
|
|
'savings': '300-500MB',
|
|
'notes': 'Distroless provides better security'
|
|
},
|
|
'centos': {
|
|
'alternatives': ['alpine:3.18', 'gcr.io/distroless/base', 'ubuntu:22.04-slim'],
|
|
'savings': '200-400MB',
|
|
'notes': 'CentOS is deprecated, migrate to alternatives'
|
|
},
|
|
'node': {
|
|
'alternatives': ['node:20-alpine', 'node:20-slim', 'gcr.io/distroless/nodejs20'],
|
|
'savings': '300-700MB',
|
|
'notes': 'Alpine is smallest, distroless is most secure'
|
|
},
|
|
'python': {
|
|
'alternatives': ['python:3.11-slim', 'python:3.11-alpine', 'gcr.io/distroless/python3'],
|
|
'savings': '400-800MB',
|
|
'notes': 'Slim balances size and compatibility'
|
|
}
|
|
}
|
|
|
|
for base_name, config in optimization_recommendations.items():
|
|
if base_name in base_image and 'slim' not in base_image and 'alpine' not in base_image:
|
|
analysis['size_impact'].append({
|
|
'issue': f'Large base image: {base_image}',
|
|
'impact': config['savings'],
|
|
'alternatives': config['alternatives'],
|
|
'recommendation': f"Switch to {config['alternatives'][0]} for optimal size/compatibility balance",
|
|
'notes': config['notes']
|
|
})
|
|
|
|
# Check for deprecated or insecure base images
|
|
deprecated_images = {
|
|
'centos:7': 'EOL reached, migrate to Rocky Linux or Alpine',
|
|
'ubuntu:18.04': 'LTS ended, upgrade to ubuntu:22.04',
|
|
'node:14': 'Node 14 is EOL, upgrade to node:18 or node:20',
|
|
'python:3.8': 'Python 3.8 will reach EOL soon, upgrade to 3.11+'
|
|
}
|
|
|
|
for deprecated, message in deprecated_images.items():
|
|
if deprecated in base_image:
|
|
analysis['security_risks'].append({
|
|
'issue': f'Deprecated base image: {deprecated}',
|
|
'severity': 'MEDIUM',
|
|
'fix': message,
|
|
'impact': 'Security vulnerabilities, no security updates'
|
|
})
|
|
|
|
def _check_layer_optimization(self, content, analysis):
|
|
"""Enhanced layer optimization analysis with modern best practices"""
|
|
lines = content.split('\n')
|
|
|
|
# Check for multiple RUN commands
|
|
run_commands = [line for line in lines if line.strip().startswith('RUN')]
|
|
if len(run_commands) > 5:
|
|
analysis['build_performance'].append({
|
|
'issue': f'Excessive RUN commands ({len(run_commands)})',
|
|
'impact': f'Creates {len(run_commands)} unnecessary layers',
|
|
'fix': 'Combine related RUN commands with && \\',
|
|
'optimization': f'Could reduce to 2-3 layers, saving ~{len(run_commands) * 10}MB'
|
|
})
|
|
|
|
# Enhanced package manager cleanup checks
|
|
package_managers = {
|
|
'apt': {
|
|
'install_pattern': r'RUN.*apt-get.*install',
|
|
'cleanup_pattern': r'rm\s+-rf\s+/var/lib/apt/lists',
|
|
'update_pattern': r'apt-get\s+update',
|
|
'combined_check': r'RUN.*apt-get\s+update.*&&.*apt-get\s+install.*&&.*rm\s+-rf\s+/var/lib/apt/lists',
|
|
'recommended_pattern': 'RUN apt-get update && apt-get install -y --no-install-recommends <packages> && rm -rf /var/lib/apt/lists/*'
|
|
},
|
|
'yum': {
|
|
'install_pattern': r'RUN.*yum.*install',
|
|
'cleanup_pattern': r'yum\s+clean\s+all',
|
|
'recommended_pattern': 'RUN yum install -y <packages> && yum clean all'
|
|
},
|
|
'apk': {
|
|
'install_pattern': r'RUN.*apk.*add',
|
|
'cleanup_pattern': r'--no-cache|rm\s+-rf\s+/var/cache/apk',
|
|
'recommended_pattern': 'RUN apk add --no-cache <packages>'
|
|
},
|
|
'pip': {
|
|
'install_pattern': r'RUN.*pip.*install',
|
|
'cleanup_pattern': r'--no-cache-dir|pip\s+cache\s+purge',
|
|
'recommended_pattern': 'RUN pip install --no-cache-dir <packages>'
|
|
}
|
|
}
|
|
|
|
for pm_name, patterns in package_managers.items():
|
|
has_install = re.search(patterns['install_pattern'], content)
|
|
has_cleanup = re.search(patterns['cleanup_pattern'], content)
|
|
|
|
if has_install and not has_cleanup:
|
|
potential_savings = {
|
|
'apt': '50-200MB',
|
|
'yum': '100-300MB',
|
|
'apk': '5-50MB',
|
|
'pip': '20-100MB'
|
|
}.get(pm_name, '10-50MB')
|
|
|
|
analysis['size_impact'].append({
|
|
'issue': f'{pm_name} package manager without cleanup',
|
|
'impact': potential_savings,
|
|
'fix': f'Add cleanup in same RUN command',
|
|
'example': patterns['recommended_pattern'],
|
|
'severity': 'MEDIUM'
|
|
})
|
|
|
|
# Check for inefficient COPY operations
|
|
copy_commands = [line for line in lines if line.strip().startswith(('COPY', 'ADD'))]
|
|
for cmd in copy_commands:
|
|
if 'COPY . .' in cmd or 'COPY ./ ./' in cmd:
|
|
analysis['build_performance'].append({
|
|
'issue': 'Inefficient COPY command copying entire context',
|
|
'impact': 'Poor build cache efficiency, slower builds',
|
|
'fix': 'Use specific COPY commands and .dockerignore',
|
|
'example': 'COPY package*.json ./ && COPY src/ ./src/',
|
|
'note': 'Copy dependency files first for better caching'
|
|
})
|
|
|
|
# Check for BuildKit optimizations
|
|
if '--mount=type=cache' not in content:
|
|
analysis['build_performance'].append({
|
|
'issue': 'Missing BuildKit cache mounts',
|
|
'impact': 'Slower builds, no dependency caching',
|
|
'fix': 'Use BuildKit cache mounts for package managers',
|
|
'example': 'RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt',
|
|
'note': 'Requires DOCKER_BUILDKIT=1'
|
|
})
|
|
|
|
# Check for multi-stage build opportunities
|
|
from_statements = re.findall(r'FROM\s+([^\s]+)', content)
|
|
if len(from_statements) == 1 and any(keyword in content.lower() for keyword in ['build', 'compile', 'npm install', 'pip install']):
|
|
analysis['size_impact'].append({
|
|
'issue': 'Single-stage build with development dependencies',
|
|
'impact': '100-500MB from build tools and dev dependencies',
|
|
'fix': 'Implement multi-stage build',
|
|
'example': 'Separate build and runtime stages',
|
|
'potential_savings': '200-800MB'
|
|
})
|
|
```
|
|
|
|
### 2. Advanced Multi-Stage Build Strategies
|
|
|
|
Implement sophisticated multi-stage builds with modern optimization techniques:
|
|
|
|
**Ultra-Optimized Multi-Stage Patterns**
|
|
```dockerfile
|
|
# Pattern 1: Node.js with Bun - Next-generation JavaScript runtime
|
|
# 5x faster installs, 4x faster runtime, 90% smaller images
|
|
FROM oven/bun:1.0-alpine AS base
|
|
|
|
# Stage 1: Dependency Resolution with Bun
|
|
FROM base AS deps
|
|
WORKDIR /app
|
|
|
|
# Bun lockfile for deterministic builds
|
|
COPY package.json bun.lockb* ./
|
|
|
|
# Ultra-fast dependency installation
|
|
RUN bun install --frozen-lockfile --production
|
|
|
|
# Stage 2: Build with development dependencies
|
|
FROM base AS build
|
|
WORKDIR /app
|
|
|
|
# Copy package files
|
|
COPY package.json bun.lockb* ./
|
|
|
|
# Install all dependencies (including dev)
|
|
RUN bun install --frozen-lockfile
|
|
|
|
# Copy source and build
|
|
COPY . .
|
|
RUN bun run build && bun test
|
|
|
|
# Stage 3: Security scanning (optional but recommended)
|
|
FROM build AS security-scan
|
|
RUN apk add --no-cache curl
|
|
# Download and run Trivy for vulnerability scanning
|
|
RUN curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin && \
|
|
trivy fs --exit-code 1 --no-progress --severity HIGH,CRITICAL /app
|
|
|
|
# Stage 4: Ultra-minimal production with distroless
|
|
FROM gcr.io/distroless/nodejs20-debian11 AS production
|
|
|
|
# Copy only what's needed for production
|
|
COPY --from=deps --chown=nonroot:nonroot /app/node_modules ./node_modules
|
|
COPY --from=build --chown=nonroot:nonroot /app/dist ./dist
|
|
COPY --from=build --chown=nonroot:nonroot /app/package.json ./
|
|
|
|
# Distroless already runs as non-root
|
|
USER nonroot
|
|
|
|
# Health check using Node.js built-in capabilities
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
CMD ["node", "-e", "require('http').get('http://localhost:3000/health',(r)=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))"]
|
|
|
|
EXPOSE 3000
|
|
CMD ["node", "dist/index.js"]
|
|
```
|
|
|
|
**Advanced Python Multi-Stage with UV Package Manager**
|
|
```dockerfile
|
|
# Pattern 2: Python with UV - 10-100x faster than pip
|
|
FROM python:3.11-slim AS base
|
|
|
|
# Install UV - next generation Python package manager
|
|
RUN pip install uv
|
|
|
|
# Stage 1: Dependency resolution with UV
|
|
FROM base AS deps
|
|
WORKDIR /app
|
|
|
|
# Copy requirements
|
|
COPY requirements.txt requirements-dev.txt ./
|
|
|
|
# Create virtual environment and install production dependencies with UV
|
|
RUN uv venv /opt/venv
|
|
ENV PATH="/opt/venv/bin:$PATH"
|
|
RUN uv pip install --no-cache -r requirements.txt
|
|
|
|
# Stage 2: Build and test
|
|
FROM base AS build
|
|
WORKDIR /app
|
|
|
|
# Install all dependencies including dev
|
|
RUN uv venv /opt/venv
|
|
ENV PATH="/opt/venv/bin:$PATH"
|
|
COPY requirements*.txt ./
|
|
RUN uv pip install --no-cache -r requirements.txt -r requirements-dev.txt
|
|
|
|
# Copy source and run tests
|
|
COPY . .
|
|
RUN python -m pytest tests/ --cov=src --cov-report=term-missing
|
|
RUN python -m black --check src/
|
|
RUN python -m isort --check-only src/
|
|
RUN python -m mypy src/
|
|
|
|
# Stage 3: Security and compliance scanning
|
|
FROM build AS security
|
|
RUN uv pip install safety bandit
|
|
RUN safety check
|
|
RUN bandit -r src/ -f json -o bandit-report.json
|
|
|
|
# Stage 4: Optimized production with distroless
|
|
FROM gcr.io/distroless/python3-debian11 AS production
|
|
|
|
# Copy virtual environment and application
|
|
COPY --from=deps /opt/venv /opt/venv
|
|
COPY --from=build /app/src ./src
|
|
COPY --from=build /app/requirements.txt ./
|
|
|
|
# Set environment for production
|
|
ENV PATH="/opt/venv/bin:$PATH" \
|
|
PYTHONUNBUFFERED=1 \
|
|
PYTHONDONTWRITEBYTECODE=1 \
|
|
PYTHONOPTIMIZE=2
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
|
|
CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)"]
|
|
|
|
EXPOSE 8000
|
|
CMD ["python", "-m", "gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "--worker-class", "uvicorn.workers.UvicornWorker", "src.main:app"]
|
|
```
|
|
|
|
**Go Static Binary with Scratch Base**
|
|
```dockerfile
|
|
# Pattern 3: Go with ultra-minimal scratch base
|
|
FROM golang:1.21-alpine AS base
|
|
|
|
# Install build dependencies
|
|
RUN apk add --no-cache git ca-certificates tzdata upx
|
|
|
|
# Stage 1: Dependency download
|
|
FROM base AS deps
|
|
WORKDIR /src
|
|
|
|
# Copy go mod files
|
|
COPY go.mod go.sum ./
|
|
|
|
# Download dependencies with module cache
|
|
RUN --mount=type=cache,target=/go/pkg/mod \
|
|
go mod download
|
|
|
|
# Stage 2: Build with optimizations
|
|
FROM base AS build
|
|
WORKDIR /src
|
|
|
|
# Copy dependencies from cache
|
|
COPY --from=deps /go/pkg /go/pkg
|
|
COPY . .
|
|
|
|
# Build static binary with extreme optimizations
|
|
RUN --mount=type=cache,target=/go/pkg/mod \
|
|
--mount=type=cache,target=/root/.cache/go-build \
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
|
-ldflags='-w -s -extldflags "-static"' \
|
|
-a -installsuffix cgo \
|
|
-trimpath \
|
|
-o app ./cmd/server
|
|
|
|
# Compress binary with UPX (optional, 50-70% size reduction)
|
|
RUN upx --best --lzma app
|
|
|
|
# Stage 3: Testing
|
|
FROM build AS test
|
|
RUN go test -v ./...
|
|
RUN go vet ./...
|
|
RUN golangci-lint run
|
|
|
|
# Stage 4: Minimal scratch image (2-5MB final image)
|
|
FROM scratch AS production
|
|
|
|
# Copy essential files
|
|
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
|
COPY --from=build /usr/share/zoneinfo /usr/share/zoneinfo
|
|
COPY --from=build /src/app /app
|
|
|
|
# Health check using app's built-in health endpoint
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
CMD ["/app", "-health-check"]
|
|
|
|
EXPOSE 8080
|
|
ENTRYPOINT ["/app"]
|
|
```
|
|
|
|
**Rust with Cross-Compilation and Security**
|
|
```dockerfile
|
|
# Pattern 4: Rust with musl for static linking
|
|
FROM rust:1.70-alpine AS base
|
|
|
|
# Install musl development tools
|
|
RUN apk add --no-cache musl-dev openssl-dev
|
|
|
|
# Stage 1: Dependency caching
|
|
FROM base AS deps
|
|
WORKDIR /app
|
|
|
|
# Copy Cargo files
|
|
COPY Cargo.toml Cargo.lock ./
|
|
|
|
# Create dummy main and build dependencies
|
|
RUN mkdir src && echo 'fn main() {}' > src/main.rs
|
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
|
--mount=type=cache,target=/app/target \
|
|
cargo build --release --target x86_64-unknown-linux-musl
|
|
|
|
# Stage 2: Build application
|
|
FROM base AS build
|
|
WORKDIR /app
|
|
|
|
# Copy dependencies from cache
|
|
COPY --from=deps /usr/local/cargo /usr/local/cargo
|
|
COPY . .
|
|
|
|
# Build optimized static binary
|
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
|
--mount=type=cache,target=/app/target \
|
|
cargo build --release --target x86_64-unknown-linux-musl && \
|
|
cp target/x86_64-unknown-linux-musl/release/app /app/app
|
|
|
|
# Strip binary for smaller size
|
|
RUN strip /app/app
|
|
|
|
# Stage 3: Security scanning
|
|
FROM build AS security
|
|
RUN cargo audit
|
|
RUN cargo clippy -- -D warnings
|
|
|
|
# Stage 4: Minimal scratch image
|
|
FROM scratch AS production
|
|
|
|
# Copy static binary
|
|
COPY --from=build /app/app /app
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
CMD ["/app", "--health"]
|
|
|
|
EXPOSE 8000
|
|
ENTRYPOINT ["/app"]
|
|
```
|
|
|
|
**Java Spring Boot with GraalVM Native Image**
|
|
```dockerfile
|
|
# Pattern 5: Java with GraalVM Native Image (sub-second startup)
|
|
FROM ghcr.io/graalvm/graalvm-ce:java17 AS base
|
|
|
|
# Install native-image component
|
|
RUN gu install native-image
|
|
|
|
# Stage 1: Dependencies
|
|
FROM base AS deps
|
|
WORKDIR /app
|
|
|
|
# Copy Maven/Gradle files
|
|
COPY pom.xml ./
|
|
COPY .mvn .mvn
|
|
COPY mvnw ./
|
|
|
|
# Download dependencies
|
|
RUN ./mvnw dependency:go-offline
|
|
|
|
# Stage 2: Build application
|
|
FROM base AS build
|
|
WORKDIR /app
|
|
|
|
# Copy dependencies and source
|
|
COPY --from=deps /root/.m2 /root/.m2
|
|
COPY . .
|
|
|
|
# Build JAR
|
|
RUN ./mvnw clean package -DskipTests
|
|
|
|
# Build native image
|
|
RUN native-image \
|
|
-jar target/*.jar \
|
|
--no-fallback \
|
|
--static \
|
|
--libc=musl \
|
|
-H:+ReportExceptionStackTraces \
|
|
-H:+AddAllCharsets \
|
|
-H:IncludeResourceBundles=sun.util.resources.TimeZoneNames \
|
|
app
|
|
|
|
# Stage 3: Testing
|
|
FROM build AS test
|
|
RUN ./mvnw test
|
|
|
|
# Stage 4: Ultra-minimal final image (20-50MB vs 200-300MB)
|
|
FROM scratch AS production
|
|
|
|
# Copy native binary
|
|
COPY --from=build /app/app /app
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=2s --retries=3 \
|
|
CMD ["/app", "--health"]
|
|
|
|
EXPOSE 8080
|
|
ENTRYPOINT ["/app"]
|
|
```
|
|
|
|
**Python Multi-Stage Example**
|
|
```dockerfile
|
|
# Stage 1: Build dependencies
|
|
FROM python:3.11-slim AS builder
|
|
|
|
# Install build dependencies
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
gcc \
|
|
libc6-dev \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Create virtual environment
|
|
RUN python -m venv /opt/venv
|
|
ENV PATH="/opt/venv/bin:$PATH"
|
|
|
|
# Install Python dependencies
|
|
COPY requirements.txt .
|
|
RUN pip install --no-cache-dir -r requirements.txt
|
|
|
|
# Stage 2: Runtime
|
|
FROM python:3.11-slim AS runtime
|
|
|
|
# Copy virtual environment from builder
|
|
COPY --from=builder /opt/venv /opt/venv
|
|
ENV PATH="/opt/venv/bin:$PATH"
|
|
|
|
# Create non-root user
|
|
RUN useradd -m -u 1001 appuser
|
|
|
|
WORKDIR /app
|
|
|
|
# Copy application
|
|
COPY --chown=appuser:appuser . .
|
|
|
|
USER appuser
|
|
|
|
# Gunicorn for production
|
|
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "app:application"]
|
|
```
|
|
|
|
### 3. Image Size Optimization
|
|
|
|
Minimize Docker image size:
|
|
|
|
**Size Reduction Techniques**
|
|
```dockerfile
|
|
# Alpine-based optimization
|
|
FROM alpine:3.18
|
|
|
|
# Install only necessary packages
|
|
RUN apk add --no-cache \
|
|
python3 \
|
|
py3-pip \
|
|
&& pip3 install --no-cache-dir --upgrade pip
|
|
|
|
# Use --no-cache-dir for pip
|
|
COPY requirements.txt .
|
|
RUN pip3 install --no-cache-dir -r requirements.txt
|
|
|
|
# Remove unnecessary files
|
|
RUN find /usr/local -type d -name __pycache__ -exec rm -rf {} + \
|
|
&& find /usr/local -type f -name '*.pyc' -delete
|
|
|
|
# Golang example with scratch image
|
|
FROM golang:1.21-alpine AS builder
|
|
WORKDIR /build
|
|
COPY . .
|
|
# Build static binary
|
|
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-s -w' -o app .
|
|
|
|
# Final stage: scratch
|
|
FROM scratch
|
|
# Copy only the binary
|
|
COPY --from=builder /build/app /app
|
|
# Copy SSL certificates for HTTPS
|
|
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
|
ENTRYPOINT ["/app"]
|
|
```
|
|
|
|
**Layer Optimization Script**
|
|
```python
|
|
def optimize_dockerfile_layers(dockerfile_content):
|
|
"""
|
|
Optimize Dockerfile layers
|
|
"""
|
|
optimizations = []
|
|
|
|
# Combine RUN commands
|
|
run_commands = re.findall(r'^RUN\s+(.+?)(?=^(?:RUN|FROM|COPY|ADD|ENV|EXPOSE|CMD|ENTRYPOINT|WORKDIR)|\Z)',
|
|
dockerfile_content, re.MULTILINE | re.DOTALL)
|
|
|
|
if len(run_commands) > 1:
|
|
combined = ' && \\\n '.join(cmd.strip() for cmd in run_commands)
|
|
optimizations.append({
|
|
'original': '\n'.join(f'RUN {cmd}' for cmd in run_commands),
|
|
'optimized': f'RUN {combined}',
|
|
'benefit': f'Reduces {len(run_commands)} layers to 1'
|
|
})
|
|
|
|
# Optimize package installation
|
|
apt_install = re.search(r'RUN\s+apt-get\s+update.*?apt-get\s+install\s+(.+?)(?=^(?:RUN|FROM)|\Z)',
|
|
dockerfile_content, re.MULTILINE | re.DOTALL)
|
|
|
|
if apt_install:
|
|
packages = apt_install.group(1)
|
|
optimized = f"""RUN apt-get update && apt-get install -y --no-install-recommends \\
|
|
{packages.strip()} \\
|
|
&& rm -rf /var/lib/apt/lists/*"""
|
|
|
|
optimizations.append({
|
|
'original': apt_install.group(0),
|
|
'optimized': optimized,
|
|
'benefit': 'Reduces image size by cleaning apt cache'
|
|
})
|
|
|
|
return optimizations
|
|
```
|
|
|
|
### 4. Build Performance Optimization
|
|
|
|
Speed up Docker builds:
|
|
|
|
**.dockerignore Optimization**
|
|
```
|
|
# .dockerignore
|
|
# Version control
|
|
.git
|
|
.gitignore
|
|
|
|
# Development
|
|
.vscode
|
|
.idea
|
|
*.swp
|
|
*.swo
|
|
|
|
# Dependencies
|
|
node_modules
|
|
vendor
|
|
venv
|
|
__pycache__
|
|
|
|
# Build artifacts
|
|
dist
|
|
build
|
|
*.egg-info
|
|
target
|
|
|
|
# Tests
|
|
test
|
|
tests
|
|
*.test.js
|
|
*.spec.js
|
|
coverage
|
|
.pytest_cache
|
|
|
|
# Documentation
|
|
docs
|
|
*.md
|
|
LICENSE
|
|
|
|
# Environment
|
|
.env
|
|
.env.*
|
|
|
|
# Logs
|
|
*.log
|
|
logs
|
|
|
|
# OS files
|
|
.DS_Store
|
|
Thumbs.db
|
|
|
|
# CI/CD
|
|
.github
|
|
.gitlab
|
|
.circleci
|
|
Jenkinsfile
|
|
|
|
# Docker
|
|
Dockerfile*
|
|
docker-compose*
|
|
.dockerignore
|
|
```
|
|
|
|
**Build Cache Optimization**
|
|
```dockerfile
|
|
# Optimize build cache
|
|
FROM node:18-alpine
|
|
|
|
WORKDIR /app
|
|
|
|
# Copy package files first (changes less frequently)
|
|
COPY package*.json ./
|
|
|
|
# Install dependencies (cached if package files haven't changed)
|
|
RUN npm ci --only=production
|
|
|
|
# Copy source code (changes frequently)
|
|
COPY . .
|
|
|
|
# Build application
|
|
RUN npm run build
|
|
|
|
# Use BuildKit cache mounts
|
|
FROM node:18-alpine AS builder
|
|
WORKDIR /app
|
|
|
|
# Mount cache for package manager
|
|
RUN --mount=type=cache,target=/root/.npm \
|
|
npm ci --only=production
|
|
|
|
# Mount cache for build artifacts
|
|
RUN --mount=type=cache,target=/app/.cache \
|
|
npm run build
|
|
```
|
|
|
|
### 5. Security Hardening
|
|
|
|
Implement security best practices:
|
|
|
|
**Security-Hardened Dockerfile**
|
|
```dockerfile
|
|
# Use specific version and minimal base image
|
|
FROM alpine:3.18.4
|
|
|
|
# Install security updates
|
|
RUN apk update && apk upgrade && apk add --no-cache \
|
|
ca-certificates \
|
|
&& rm -rf /var/cache/apk/*
|
|
|
|
# Create non-root user
|
|
RUN addgroup -g 1001 -S appgroup && \
|
|
adduser -S appuser -u 1001 -G appgroup
|
|
|
|
# Set secure permissions
|
|
RUN mkdir /app && chown -R appuser:appgroup /app
|
|
WORKDIR /app
|
|
|
|
# Copy with correct ownership
|
|
COPY --chown=appuser:appgroup . .
|
|
|
|
# Drop all capabilities
|
|
USER appuser
|
|
|
|
# Read-only root filesystem
|
|
# Add volumes for writable directories
|
|
VOLUME ["/tmp", "/app/logs"]
|
|
|
|
# Security labels
|
|
LABEL security.scan="trivy" \
|
|
security.updates="auto"
|
|
|
|
# Health check with timeout
|
|
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
|
|
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
|
|
|
|
# Run as PID 1 to handle signals properly
|
|
ENTRYPOINT ["dumb-init", "--"]
|
|
CMD ["./app"]
|
|
```
|
|
|
|
**Security Scanning Integration**
|
|
```yaml
|
|
# .github/workflows/docker-security.yml
|
|
name: Docker Security Scan
|
|
|
|
on:
|
|
push:
|
|
paths:
|
|
- 'Dockerfile*'
|
|
- '.dockerignore'
|
|
|
|
jobs:
|
|
scan:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
|
|
- name: Run Trivy vulnerability scanner
|
|
uses: aquasecurity/trivy-action@master
|
|
with:
|
|
image-ref: '${{ github.repository }}:${{ github.sha }}'
|
|
format: 'sarif'
|
|
output: 'trivy-results.sarif'
|
|
severity: 'CRITICAL,HIGH'
|
|
|
|
- name: Upload Trivy scan results
|
|
uses: github/codeql-action/upload-sarif@v2
|
|
with:
|
|
sarif_file: 'trivy-results.sarif'
|
|
|
|
- name: Run Hadolint
|
|
uses: hadolint/hadolint-action@v3.1.0
|
|
with:
|
|
dockerfile: Dockerfile
|
|
format: sarif
|
|
output-file: hadolint-results.sarif
|
|
|
|
- name: Upload Hadolint scan results
|
|
uses: github/codeql-action/upload-sarif@v2
|
|
with:
|
|
sarif_file: hadolint-results.sarif
|
|
```
|
|
|
|
### 6. Runtime Optimization
|
|
|
|
Optimize container runtime performance:
|
|
|
|
**Runtime Configuration**
|
|
```dockerfile
|
|
# JVM optimization example
|
|
FROM eclipse-temurin:17-jre-alpine
|
|
|
|
# JVM memory settings based on container limits
|
|
ENV JAVA_OPTS="-XX:MaxRAMPercentage=75.0 \
|
|
-XX:InitialRAMPercentage=50.0 \
|
|
-XX:+UseContainerSupport \
|
|
-XX:+OptimizeStringConcat \
|
|
-XX:+UseStringDeduplication \
|
|
-Djava.security.egd=file:/dev/./urandom"
|
|
|
|
# Node.js optimization
|
|
FROM node:18-alpine
|
|
ENV NODE_ENV=production \
|
|
NODE_OPTIONS="--max-old-space-size=1024 --optimize-for-size"
|
|
|
|
# Python optimization
|
|
FROM python:3.11-slim
|
|
ENV PYTHONUNBUFFERED=1 \
|
|
PYTHONDONTWRITEBYTECODE=1 \
|
|
PYTHONOPTIMIZE=2
|
|
|
|
# Nginx optimization
|
|
FROM nginx:alpine
|
|
COPY nginx-optimized.conf /etc/nginx/nginx.conf
|
|
# Enable gzip, caching, and connection pooling
|
|
```
|
|
|
|
### 7. Docker Compose Optimization
|
|
|
|
Optimize multi-container applications:
|
|
|
|
```yaml
|
|
# docker-compose.yml
|
|
version: '3.9'
|
|
|
|
services:
|
|
app:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
cache_from:
|
|
- ${REGISTRY}/app:latest
|
|
- ${REGISTRY}/app:builder
|
|
args:
|
|
BUILDKIT_INLINE_CACHE: 1
|
|
image: ${REGISTRY}/app:${VERSION:-latest}
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1'
|
|
memory: 512M
|
|
reservations:
|
|
cpus: '0.5'
|
|
memory: 256M
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
restart: unless-stopped
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
volumes:
|
|
- type: tmpfs
|
|
target: /data
|
|
tmpfs:
|
|
size: 268435456 # 256MB
|
|
|
|
nginx:
|
|
image: nginx:alpine
|
|
volumes:
|
|
- type: bind
|
|
source: ./nginx.conf
|
|
target: /etc/nginx/nginx.conf
|
|
read_only: true
|
|
depends_on:
|
|
app:
|
|
condition: service_healthy
|
|
```
|
|
|
|
### 8. Build Automation
|
|
|
|
Automate optimized builds:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# build-optimize.sh
|
|
|
|
set -euo pipefail
|
|
|
|
# Variables
|
|
IMAGE_NAME="${1:-myapp}"
|
|
VERSION="${2:-latest}"
|
|
PLATFORMS="${3:-linux/amd64,linux/arm64}"
|
|
|
|
echo "🏗️ Building optimized Docker image..."
|
|
|
|
# Enable BuildKit
|
|
export DOCKER_BUILDKIT=1
|
|
|
|
# Build with cache
|
|
docker buildx build \
|
|
--platform "${PLATFORMS}" \
|
|
--cache-from "type=registry,ref=${IMAGE_NAME}:buildcache" \
|
|
--cache-to "type=registry,ref=${IMAGE_NAME}:buildcache,mode=max" \
|
|
--tag "${IMAGE_NAME}:${VERSION}" \
|
|
--build-arg BUILDKIT_INLINE_CACHE=1 \
|
|
--progress=plain \
|
|
--push \
|
|
.
|
|
|
|
# Analyze image size
|
|
echo "📊 Image analysis:"
|
|
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
|
|
wagoodman/dive:latest "${IMAGE_NAME}:${VERSION}"
|
|
|
|
# Security scan
|
|
echo "🔒 Security scan:"
|
|
trivy image "${IMAGE_NAME}:${VERSION}"
|
|
|
|
# Size report
|
|
echo "📏 Size comparison:"
|
|
docker images "${IMAGE_NAME}" --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
|
|
```
|
|
|
|
### 9. Monitoring and Metrics
|
|
|
|
Track container performance:
|
|
|
|
```python
|
|
# container-metrics.py
|
|
import docker
|
|
import json
|
|
from datetime import datetime
|
|
|
|
class ContainerMonitor:
|
|
def __init__(self):
|
|
self.client = docker.from_env()
|
|
|
|
def collect_metrics(self, container_name):
|
|
"""Collect container performance metrics"""
|
|
container = self.client.containers.get(container_name)
|
|
stats = container.stats(stream=False)
|
|
|
|
metrics = {
|
|
'timestamp': datetime.now().isoformat(),
|
|
'container': container_name,
|
|
'cpu': self._calculate_cpu_percent(stats),
|
|
'memory': self._calculate_memory_usage(stats),
|
|
'network': self._calculate_network_io(stats),
|
|
'disk': self._calculate_disk_io(stats)
|
|
}
|
|
|
|
return metrics
|
|
|
|
def _calculate_cpu_percent(self, stats):
|
|
"""Calculate CPU usage percentage"""
|
|
cpu_delta = stats['cpu_stats']['cpu_usage']['total_usage'] - \
|
|
stats['precpu_stats']['cpu_usage']['total_usage']
|
|
system_delta = stats['cpu_stats']['system_cpu_usage'] - \
|
|
stats['precpu_stats']['system_cpu_usage']
|
|
|
|
if system_delta > 0 and cpu_delta > 0:
|
|
cpu_percent = (cpu_delta / system_delta) * \
|
|
len(stats['cpu_stats']['cpu_usage']['percpu_usage']) * 100.0
|
|
return round(cpu_percent, 2)
|
|
return 0.0
|
|
|
|
def _calculate_memory_usage(self, stats):
|
|
"""Calculate memory usage"""
|
|
usage = stats['memory_stats']['usage']
|
|
limit = stats['memory_stats']['limit']
|
|
|
|
return {
|
|
'usage_bytes': usage,
|
|
'limit_bytes': limit,
|
|
'percent': round((usage / limit) * 100, 2)
|
|
}
|
|
```
|
|
|
|
### 10. Best Practices Checklist
|
|
|
|
```python
|
|
def generate_dockerfile_checklist():
|
|
"""Generate Dockerfile best practices checklist"""
|
|
checklist = """
|
|
## Dockerfile Best Practices Checklist
|
|
|
|
### Base Image
|
|
- [ ] Use specific version tags (not :latest)
|
|
- [ ] Use minimal base images (alpine, slim, distroless)
|
|
- [ ] Keep base images updated
|
|
- [ ] Use official images when possible
|
|
|
|
### Layers & Caching
|
|
- [ ] Order commands from least to most frequently changing
|
|
- [ ] Combine RUN commands where appropriate
|
|
- [ ] Clean up in the same layer (apt cache, pip cache)
|
|
- [ ] Use .dockerignore to exclude unnecessary files
|
|
|
|
### Security
|
|
- [ ] Run as non-root user
|
|
- [ ] Don't store secrets in images
|
|
- [ ] Scan images for vulnerabilities
|
|
- [ ] Use COPY instead of ADD
|
|
- [ ] Set read-only root filesystem where possible
|
|
|
|
### Size Optimization
|
|
- [ ] Use multi-stage builds
|
|
- [ ] Remove unnecessary dependencies
|
|
- [ ] Clear package manager caches
|
|
- [ ] Remove temporary files and build artifacts
|
|
- [ ] Use --no-install-recommends for apt
|
|
|
|
### Performance
|
|
- [ ] Set appropriate resource limits
|
|
- [ ] Use health checks
|
|
- [ ] Optimize for startup time
|
|
- [ ] Configure logging appropriately
|
|
- [ ] Use BuildKit for faster builds
|
|
|
|
### Maintainability
|
|
- [ ] Include LABEL metadata
|
|
- [ ] Document exposed ports with EXPOSE
|
|
- [ ] Use ARG for build-time variables
|
|
- [ ] Include meaningful comments
|
|
- [ ] Version your Dockerfiles
|
|
"""
|
|
return checklist
|
|
```
|
|
|
|
## Output Format
|
|
|
|
1. **Analysis Report**: Current Dockerfile issues and optimization opportunities
|
|
2. **Optimized Dockerfile**: Rewritten Dockerfile with all optimizations
|
|
3. **Size Comparison**: Before/after image size analysis
|
|
4. **Build Performance**: Build time improvements and caching strategy
|
|
5. **Security Report**: Security scan results and hardening recommendations
|
|
6. **Runtime Config**: Optimized runtime settings for the application
|
|
7. **Monitoring Setup**: Container metrics and performance tracking
|
|
8. **Migration Guide**: Step-by-step guide to implement optimizations
|
|
|
|
## Cross-Command Integration
|
|
|
|
### Complete Container-First Development Workflow
|
|
|
|
**Containerized Development Pipeline**
|
|
```bash
|
|
# 1. Generate containerized API scaffolding
|
|
/api-scaffold
|
|
framework: "fastapi"
|
|
deployment_target: "kubernetes"
|
|
containerization: true
|
|
monitoring: true
|
|
|
|
# 2. Optimize containers for production
|
|
/docker-optimize
|
|
optimization_level: "production"
|
|
security_hardening: true
|
|
multi_stage_build: true
|
|
|
|
# 3. Security scan container images
|
|
/security-scan
|
|
scan_types: ["container", "dockerfile", "runtime"]
|
|
image_name: "app:optimized"
|
|
generate_sbom: true
|
|
|
|
# 4. Generate K8s manifests for optimized containers
|
|
/k8s-manifest
|
|
container_security: "strict"
|
|
resource_optimization: true
|
|
horizontal_scaling: true
|
|
```
|
|
|
|
**Integrated Container Configuration**
|
|
```python
|
|
# container-config.py - Shared across all commands
|
|
class IntegratedContainerConfig:
|
|
def __init__(self):
|
|
self.api_config = self.load_api_config() # From /api-scaffold
|
|
self.security_config = self.load_security_config() # From /security-scan
|
|
self.k8s_config = self.load_k8s_config() # From /k8s-manifest
|
|
self.test_config = self.load_test_config() # From /test-harness
|
|
|
|
def generate_optimized_dockerfile(self):
|
|
"""Generate Dockerfile optimized for the specific application"""
|
|
framework = self.api_config.get('framework', 'python')
|
|
security_level = self.security_config.get('level', 'standard')
|
|
deployment_target = self.k8s_config.get('platform', 'kubernetes')
|
|
|
|
if framework == 'fastapi':
|
|
return self.generate_fastapi_dockerfile(security_level, deployment_target)
|
|
elif framework == 'express':
|
|
return self.generate_express_dockerfile(security_level, deployment_target)
|
|
elif framework == 'django':
|
|
return self.generate_django_dockerfile(security_level, deployment_target)
|
|
|
|
def generate_fastapi_dockerfile(self, security_level, deployment_target):
|
|
"""Generate optimized FastAPI Dockerfile"""
|
|
dockerfile_content = {
|
|
'base_image': self.select_base_image('python', security_level),
|
|
'build_stages': self.configure_build_stages(),
|
|
'security_configs': self.apply_security_configurations(security_level),
|
|
'runtime_optimizations': self.configure_runtime_optimizations(),
|
|
'monitoring_setup': self.configure_monitoring_setup(),
|
|
'health_checks': self.configure_health_checks()
|
|
}
|
|
return dockerfile_content
|
|
|
|
def select_base_image(self, language, security_level):
|
|
"""Select optimal base image based on security and size requirements"""
|
|
base_images = {
|
|
'python': {
|
|
'minimal': 'python:3.11-alpine',
|
|
'standard': 'python:3.11-slim-bookworm',
|
|
'secure': 'chainguard/python:latest-dev',
|
|
'distroless': 'gcr.io/distroless/python3-debian12'
|
|
}
|
|
}
|
|
|
|
if security_level == 'strict':
|
|
return base_images[language]['distroless']
|
|
elif security_level == 'enhanced':
|
|
return base_images[language]['secure']
|
|
else:
|
|
return base_images[language]['standard']
|
|
|
|
def configure_build_stages(self):
|
|
"""Configure multi-stage build optimization"""
|
|
return {
|
|
'dependencies_stage': {
|
|
'name': 'dependencies',
|
|
'base': 'python:3.11-slim-bookworm',
|
|
'actions': [
|
|
'COPY requirements.txt .',
|
|
'RUN pip install --no-cache-dir --user -r requirements.txt'
|
|
]
|
|
},
|
|
'security_stage': {
|
|
'name': 'security-scan',
|
|
'base': 'dependencies',
|
|
'actions': [
|
|
'RUN pip-audit --format=json --output=/tmp/security-report.json',
|
|
'RUN safety check --json --output=/tmp/safety-report.json'
|
|
]
|
|
},
|
|
'runtime_stage': {
|
|
'name': 'runtime',
|
|
'base': 'python:3.11-slim-bookworm',
|
|
'actions': [
|
|
'COPY --from=dependencies /root/.local /root/.local',
|
|
'COPY --from=security-scan /tmp/*-report.json /security-reports/'
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
**API Container Integration**
|
|
```dockerfile
|
|
# Dockerfile.api - Generated from /api-scaffold + /docker-optimize
|
|
# Multi-stage build optimized for FastAPI applications
|
|
FROM python:3.11-slim-bookworm AS base
|
|
|
|
# Set environment variables for optimization
|
|
ENV PYTHONUNBUFFERED=1 \
|
|
PYTHONDONTWRITEBYTECODE=1 \
|
|
PIP_NO_CACHE_DIR=1 \
|
|
PIP_DISABLE_PIP_VERSION_CHECK=1
|
|
|
|
# Stage 1: Dependencies
|
|
FROM base AS dependencies
|
|
WORKDIR /app
|
|
|
|
# Install system dependencies for building Python packages
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
build-essential \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Copy and install Python dependencies
|
|
COPY requirements.txt .
|
|
RUN pip install --user --no-warn-script-location -r requirements.txt
|
|
|
|
# Stage 2: Security scanning
|
|
FROM dependencies AS security-scan
|
|
RUN pip install --user pip-audit safety bandit
|
|
|
|
# Copy source code for security scanning
|
|
COPY . .
|
|
|
|
# Run security scans during build
|
|
RUN python -m bandit -r . -f json -o /tmp/bandit-report.json || true
|
|
RUN python -m safety check --json --output /tmp/safety-report.json || true
|
|
RUN python -m pip_audit --format=json --output=/tmp/pip-audit-report.json || true
|
|
|
|
# Stage 3: Testing (optional, can be skipped in production builds)
|
|
FROM security-scan AS testing
|
|
RUN pip install --user pytest pytest-cov
|
|
|
|
# Run tests during build (from /test-harness integration)
|
|
RUN python -m pytest tests/ --cov=src --cov-report=json --cov-report=term
|
|
|
|
# Stage 4: Production runtime
|
|
FROM base AS runtime
|
|
|
|
# Create non-root user for security
|
|
RUN groupadd -r appuser && useradd -r -g appuser appuser
|
|
|
|
# Set up application directory
|
|
WORKDIR /app
|
|
RUN chown appuser:appuser /app
|
|
|
|
# Copy Python packages from dependencies stage
|
|
COPY --from=dependencies --chown=appuser:appuser /root/.local /home/appuser/.local
|
|
|
|
# Copy security reports from security stage
|
|
COPY --from=security-scan /tmp/*-report.json /app/security-reports/
|
|
|
|
# Copy application code
|
|
COPY --chown=appuser:appuser . .
|
|
|
|
# Update PATH to include user packages
|
|
ENV PATH=/home/appuser/.local/bin:$PATH
|
|
|
|
# Switch to non-root user
|
|
USER appuser
|
|
|
|
# Configure health check (integrates with K8s health checks)
|
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
|
CMD python -c "import requests; requests.get('http://localhost:8000/health', timeout=5)"
|
|
|
|
# Expose port (configured from API scaffold)
|
|
EXPOSE 8000
|
|
|
|
# Set optimal startup command
|
|
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
|
|
```
|
|
|
|
**Database Container Integration**
|
|
```dockerfile
|
|
# Dockerfile.db - Generated for database migrations from /db-migrate
|
|
FROM postgres:15-alpine AS base
|
|
|
|
# Install migration tools
|
|
RUN apk add --no-cache python3 py3-pip
|
|
RUN pip3 install alembic psycopg2-binary
|
|
|
|
# Create migration user
|
|
RUN addgroup -g 1001 migration && adduser -D -u 1001 -G migration migration
|
|
|
|
# Stage 1: Migration preparation
|
|
FROM base AS migration-prep
|
|
WORKDIR /migrations
|
|
|
|
# Copy migration scripts from /db-migrate output
|
|
COPY --chown=migration:migration migrations/ ./
|
|
COPY --chown=migration:migration alembic.ini ./
|
|
|
|
# Validate migration scripts
|
|
USER migration
|
|
RUN alembic check || echo "Migration validation completed"
|
|
|
|
# Stage 2: Production database
|
|
FROM postgres:15-alpine AS production
|
|
|
|
# Copy validated migrations
|
|
COPY --from=migration-prep --chown=postgres:postgres /migrations /docker-entrypoint-initdb.d/
|
|
|
|
# Configure PostgreSQL for production
|
|
RUN echo "shared_preload_libraries = 'pg_stat_statements'" >> /usr/local/share/postgresql/postgresql.conf.sample
|
|
RUN echo "track_activity_query_size = 2048" >> /usr/local/share/postgresql/postgresql.conf.sample
|
|
RUN echo "log_min_duration_statement = 1000" >> /usr/local/share/postgresql/postgresql.conf.sample
|
|
|
|
# Security configurations from /security-scan
|
|
RUN echo "ssl = on" >> /usr/local/share/postgresql/postgresql.conf.sample
|
|
RUN echo "log_connections = on" >> /usr/local/share/postgresql/postgresql.conf.sample
|
|
RUN echo "log_disconnections = on" >> /usr/local/share/postgresql/postgresql.conf.sample
|
|
|
|
EXPOSE 5432
|
|
```
|
|
|
|
**Frontend Container Integration**
|
|
```dockerfile
|
|
# Dockerfile.frontend - Generated from /frontend-optimize + /docker-optimize
|
|
# Multi-stage build for React/Vue applications
|
|
FROM node:18-alpine AS base
|
|
|
|
# Set environment variables
|
|
ENV NODE_ENV=production \
|
|
NPM_CONFIG_CACHE=/tmp/.npm
|
|
|
|
# Stage 1: Dependencies
|
|
FROM base AS dependencies
|
|
WORKDIR /app
|
|
|
|
# Copy package files
|
|
COPY package*.json ./
|
|
|
|
# Install dependencies with optimization
|
|
RUN npm ci --only=production --silent
|
|
|
|
# Stage 2: Build application
|
|
FROM base AS build
|
|
WORKDIR /app
|
|
|
|
# Copy dependencies
|
|
COPY --from=dependencies /app/node_modules ./node_modules
|
|
|
|
# Copy source code
|
|
COPY . .
|
|
|
|
# Build application with optimizations from /frontend-optimize
|
|
RUN npm run build
|
|
|
|
# Run security audit
|
|
RUN npm audit --audit-level high --production
|
|
|
|
# Stage 3: Security scanning
|
|
FROM build AS security-scan
|
|
|
|
# Install security scanning tools
|
|
RUN npm install -g retire snyk
|
|
|
|
# Run security scans
|
|
RUN retire --outputformat json --outputpath /tmp/retire-report.json || true
|
|
RUN snyk test --json > /tmp/snyk-report.json || true
|
|
|
|
# Stage 4: Production server
|
|
FROM nginx:alpine AS production
|
|
|
|
# Install security updates
|
|
RUN apk update && apk upgrade && apk add --no-cache dumb-init
|
|
|
|
# Create non-root user
|
|
RUN addgroup -g 1001 www && adduser -D -u 1001 -G www www
|
|
|
|
# Copy built application
|
|
COPY --from=build --chown=www:www /app/dist /usr/share/nginx/html
|
|
|
|
# Copy security reports
|
|
COPY --from=security-scan /tmp/*-report.json /var/log/security/
|
|
|
|
# Copy optimized nginx configuration
|
|
COPY nginx.conf /etc/nginx/nginx.conf
|
|
|
|
# Configure proper file permissions
|
|
RUN chown -R www:www /usr/share/nginx/html
|
|
RUN chmod -R 755 /usr/share/nginx/html
|
|
|
|
# Use non-root user
|
|
USER www
|
|
|
|
# Health check for frontend
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
CMD wget --no-verbose --tries=1 --spider http://localhost:80/ || exit 1
|
|
|
|
EXPOSE 80
|
|
|
|
# Use dumb-init for proper signal handling
|
|
ENTRYPOINT ["dumb-init", "--"]
|
|
CMD ["nginx", "-g", "daemon off;"]
|
|
```
|
|
|
|
**Kubernetes Container Integration**
|
|
```yaml
|
|
# k8s-optimized-deployment.yaml - From /k8s-manifest + /docker-optimize
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: container-config
|
|
namespace: production
|
|
data:
|
|
optimization-level: "production"
|
|
security-level: "strict"
|
|
monitoring-enabled: "true"
|
|
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: optimized-api
|
|
namespace: production
|
|
labels:
|
|
app: api
|
|
optimization: enabled
|
|
spec:
|
|
replicas: 3
|
|
strategy:
|
|
type: RollingUpdate
|
|
rollingUpdate:
|
|
maxUnavailable: 1
|
|
maxSurge: 1
|
|
selector:
|
|
matchLabels:
|
|
app: api
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: api
|
|
annotations:
|
|
# Container optimization annotations
|
|
container.seccomp.security.alpha.kubernetes.io/defaultProfileName: runtime/default
|
|
container.apparmor.security.beta.kubernetes.io/api: runtime/default
|
|
spec:
|
|
# Optimized pod configuration
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 1001
|
|
runAsGroup: 1001
|
|
fsGroup: 1001
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
|
|
# Resource optimization from container analysis
|
|
containers:
|
|
- name: api
|
|
image: registry.company.com/api:optimized-latest
|
|
imagePullPolicy: Always
|
|
|
|
# Optimized resource allocation
|
|
resources:
|
|
requests:
|
|
memory: "128Mi" # Optimized based on actual usage
|
|
cpu: "100m" # Optimized based on load testing
|
|
ephemeral-storage: "1Gi"
|
|
limits:
|
|
memory: "512Mi" # Prevents OOM, allows burst
|
|
cpu: "500m" # Allows processing spikes
|
|
ephemeral-storage: "2Gi"
|
|
|
|
# Container security optimization
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
runAsNonRoot: true
|
|
runAsUser: 1001
|
|
capabilities:
|
|
drop:
|
|
- ALL
|
|
add:
|
|
- NET_BIND_SERVICE
|
|
|
|
# Optimized startup and health checks
|
|
ports:
|
|
- containerPort: 8000
|
|
protocol: TCP
|
|
|
|
# Fast startup probe
|
|
startupProbe:
|
|
httpGet:
|
|
path: /startup
|
|
port: 8000
|
|
failureThreshold: 30
|
|
periodSeconds: 1
|
|
|
|
# Optimized health checks
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8000
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /ready
|
|
port: 8000
|
|
initialDelaySeconds: 2
|
|
periodSeconds: 5
|
|
timeoutSeconds: 3
|
|
|
|
# Environment variables from container optimization
|
|
env:
|
|
- name: OPTIMIZATION_LEVEL
|
|
valueFrom:
|
|
configMapKeyRef:
|
|
name: container-config
|
|
key: optimization-level
|
|
- name: PYTHONUNBUFFERED
|
|
value: "1"
|
|
- name: WORKERS
|
|
value: "4"
|
|
|
|
# Optimized volume mounts
|
|
volumeMounts:
|
|
- name: tmp-volume
|
|
mountPath: /tmp
|
|
- name: cache-volume
|
|
mountPath: /app/cache
|
|
- name: security-reports
|
|
mountPath: /app/security-reports
|
|
readOnly: true
|
|
|
|
# Optimized volumes
|
|
volumes:
|
|
- name: tmp-volume
|
|
emptyDir:
|
|
sizeLimit: 100Mi
|
|
- name: cache-volume
|
|
emptyDir:
|
|
sizeLimit: 500Mi
|
|
- name: security-reports
|
|
configMap:
|
|
name: security-reports
|
|
|
|
---
|
|
# Horizontal Pod Autoscaler with container metrics
|
|
apiVersion: autoscaling/v2
|
|
kind: HorizontalPodAutoscaler
|
|
metadata:
|
|
name: api-hpa
|
|
namespace: production
|
|
spec:
|
|
scaleTargetRef:
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
name: optimized-api
|
|
minReplicas: 2
|
|
maxReplicas: 10
|
|
metrics:
|
|
- type: Resource
|
|
resource:
|
|
name: cpu
|
|
target:
|
|
type: Utilization
|
|
averageUtilization: 70
|
|
- type: Resource
|
|
resource:
|
|
name: memory
|
|
target:
|
|
type: Utilization
|
|
averageUtilization: 80
|
|
behavior:
|
|
scaleDown:
|
|
stabilizationWindowSeconds: 300
|
|
policies:
|
|
- type: Percent
|
|
value: 50
|
|
periodSeconds: 60
|
|
scaleUp:
|
|
stabilizationWindowSeconds: 60
|
|
policies:
|
|
- type: Percent
|
|
value: 100
|
|
periodSeconds: 15
|
|
|
|
---
|
|
# Pod Disruption Budget for rolling updates
|
|
apiVersion: policy/v1
|
|
kind: PodDisruptionBudget
|
|
metadata:
|
|
name: api-pdb
|
|
namespace: production
|
|
spec:
|
|
minAvailable: 1
|
|
selector:
|
|
matchLabels:
|
|
app: api
|
|
```
|
|
|
|
**CI/CD Container Integration**
|
|
```yaml
|
|
# .github/workflows/container-pipeline.yml
|
|
name: Optimized Container Pipeline
|
|
|
|
on:
|
|
push:
|
|
branches: [main, develop]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
env:
|
|
REGISTRY: ghcr.io
|
|
IMAGE_NAME: ${{ github.repository }}
|
|
|
|
jobs:
|
|
build-and-optimize:
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
security-events: write
|
|
|
|
strategy:
|
|
matrix:
|
|
service: [api, frontend, database]
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
# 1. Build multi-stage container
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
with:
|
|
driver-opts: network=host
|
|
|
|
- name: Log in to Container Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
# 2. Build optimized images
|
|
- name: Build and push container images
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: .
|
|
file: Dockerfile.${{ matrix.service }}
|
|
push: true
|
|
tags: |
|
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.service }}:${{ github.sha }}
|
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.service }}:latest
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
platforms: linux/amd64,linux/arm64
|
|
|
|
# 3. Container security scanning
|
|
- name: Run Trivy vulnerability scanner
|
|
uses: aquasecurity/trivy-action@master
|
|
with:
|
|
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.service }}:${{ github.sha }}
|
|
format: 'sarif'
|
|
output: 'trivy-results-${{ matrix.service }}.sarif'
|
|
|
|
# 4. Container optimization analysis
|
|
- name: Analyze container optimization
|
|
run: |
|
|
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | \
|
|
grep ${{ matrix.service }} > container-analysis-${{ matrix.service }}.txt
|
|
|
|
# Compare with baseline
|
|
if [ -f baseline-sizes.txt ]; then
|
|
echo "Size comparison for ${{ matrix.service }}:" >> size-comparison.txt
|
|
echo "Previous: $(grep ${{ matrix.service }} baseline-sizes.txt || echo 'N/A')" >> size-comparison.txt
|
|
echo "Current: $(grep ${{ matrix.service }} container-analysis-${{ matrix.service }}.txt)" >> size-comparison.txt
|
|
fi
|
|
|
|
# 5. Performance testing
|
|
- name: Container performance testing
|
|
run: |
|
|
# Start container for performance testing
|
|
docker run -d --name test-${{ matrix.service }} \
|
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.service }}:${{ github.sha }}
|
|
|
|
# Wait for startup
|
|
sleep 30
|
|
|
|
# Run basic performance tests
|
|
if [ "${{ matrix.service }}" = "api" ]; then
|
|
docker exec test-${{ matrix.service }} \
|
|
python -c "import requests; print(requests.get('http://localhost:8000/health').status_code)"
|
|
fi
|
|
|
|
# Cleanup
|
|
docker stop test-${{ matrix.service }}
|
|
docker rm test-${{ matrix.service }}
|
|
|
|
# 6. Upload security results
|
|
- name: Upload Trivy scan results to GitHub Security tab
|
|
uses: github/codeql-action/upload-sarif@v2
|
|
with:
|
|
sarif_file: 'trivy-results-${{ matrix.service }}.sarif'
|
|
|
|
# 7. Generate optimization report
|
|
- name: Generate optimization report
|
|
run: |
|
|
cat > optimization-report-${{ matrix.service }}.md << EOF
|
|
# Container Optimization Report - ${{ matrix.service }}
|
|
|
|
## Build Information
|
|
- **Image**: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.service }}:${{ github.sha }}
|
|
- **Build Date**: $(date)
|
|
- **Platforms**: linux/amd64, linux/arm64
|
|
|
|
## Size Analysis
|
|
$(cat container-analysis-${{ matrix.service }}.txt)
|
|
|
|
## Security Scan
|
|
- **Scanner**: Trivy
|
|
- **Results**: See Security tab for detailed findings
|
|
|
|
## Optimizations Applied
|
|
- Multi-stage build for minimal image size
|
|
- Security hardening with non-root user
|
|
- Layer caching for faster builds
|
|
- Health checks for reliability
|
|
EOF
|
|
|
|
- name: Upload optimization report
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: optimization-report-${{ matrix.service }}
|
|
path: optimization-report-${{ matrix.service }}.md
|
|
|
|
deploy-to-staging:
|
|
needs: build-and-optimize
|
|
runs-on: ubuntu-latest
|
|
if: github.ref == 'refs/heads/develop'
|
|
|
|
steps:
|
|
- name: Deploy to staging
|
|
run: |
|
|
# Update K8s manifests with new image tags
|
|
# Apply optimized K8s configurations
|
|
kubectl set image deployment/optimized-api \
|
|
api=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/api:${{ github.sha }} \
|
|
--namespace=staging
|
|
```
|
|
|
|
**Monitoring Integration**
|
|
```python
|
|
# container_monitoring.py - Integrated container monitoring
|
|
import docker
|
|
import psutil
|
|
from prometheus_client import CollectorRegistry, Gauge, Counter, Histogram
|
|
from typing import Dict, Any
|
|
|
|
class ContainerOptimizationMonitor:
|
|
"""Monitor container performance and optimization metrics"""
|
|
|
|
def __init__(self):
|
|
self.docker_client = docker.from_env()
|
|
self.registry = CollectorRegistry()
|
|
|
|
# Metrics from container optimization
|
|
self.container_size_gauge = Gauge(
|
|
'container_image_size_bytes',
|
|
'Container image size in bytes',
|
|
['service', 'optimization_level'],
|
|
registry=self.registry
|
|
)
|
|
|
|
self.container_startup_time = Histogram(
|
|
'container_startup_seconds',
|
|
'Container startup time in seconds',
|
|
['service'],
|
|
registry=self.registry
|
|
)
|
|
|
|
self.resource_usage_gauge = Gauge(
|
|
'container_resource_usage_ratio',
|
|
'Container resource usage ratio (used/limit)',
|
|
['service', 'resource_type'],
|
|
registry=self.registry
|
|
)
|
|
|
|
def monitor_optimization_metrics(self):
|
|
"""Monitor container optimization effectiveness"""
|
|
containers = self.docker_client.containers.list()
|
|
|
|
optimization_metrics = {}
|
|
|
|
for container in containers:
|
|
service_name = container.labels.get('app', 'unknown')
|
|
|
|
# Monitor image size efficiency
|
|
image = container.image
|
|
size_mb = self.get_image_size(image.id) / (1024 * 1024)
|
|
|
|
# Monitor resource efficiency
|
|
stats = container.stats(stream=False)
|
|
memory_usage = self.calculate_memory_efficiency(stats)
|
|
cpu_usage = self.calculate_cpu_efficiency(stats)
|
|
|
|
# Monitor startup performance
|
|
startup_time = self.get_container_startup_time(container)
|
|
|
|
optimization_metrics[service_name] = {
|
|
'image_size_mb': size_mb,
|
|
'memory_efficiency': memory_usage,
|
|
'cpu_efficiency': cpu_usage,
|
|
'startup_time_seconds': startup_time,
|
|
'optimization_score': self.calculate_optimization_score(
|
|
size_mb, memory_usage, cpu_usage, startup_time
|
|
)
|
|
}
|
|
|
|
# Update Prometheus metrics
|
|
self.container_size_gauge.labels(
|
|
service=service_name,
|
|
optimization_level='production'
|
|
).set(size_mb)
|
|
|
|
self.container_startup_time.labels(
|
|
service=service_name
|
|
).observe(startup_time)
|
|
|
|
return optimization_metrics
|
|
|
|
def calculate_optimization_score(self, size_mb, memory_eff, cpu_eff, startup_time):
|
|
"""Calculate overall optimization score (0-100)"""
|
|
size_score = max(0, 100 - (size_mb / 10)) # Penalty for large images
|
|
memory_score = (1 - memory_eff) * 100 # Reward for efficient memory use
|
|
cpu_score = (1 - cpu_eff) * 100 # Reward for efficient CPU use
|
|
startup_score = max(0, 100 - startup_time * 10) # Penalty for slow startup
|
|
|
|
return (size_score + memory_score + cpu_score + startup_score) / 4
|
|
```
|
|
|
|
This comprehensive integration ensures containers are optimized across the entire development lifecycle, from build-time optimization through runtime monitoring and Kubernetes deployment. |