Phase 1: Initial Setup
#### Create .dockerignore
Exclude unnecessary files from build context:
```dockerignore
node_modules/
__pycache__/
*.pyc
.git/
.env
*.log
dist/
build/
coverage/
```
See examples/.dockerignore for comprehensive template.
Key principles:
- Exclude build artifacts and dependencies
- Exclude sensitive files (.env, credentials)
- Exclude version control (.git)
- Smaller context = faster builds
#### Analyze Application Requirements
Determine:
- Runtime (Node.js, Python, Go, Java)
- Dependencies and package managers
- Build vs. runtime requirements
- Port exposure and volume needs
Phase 2: Multi-Stage Dockerfile
#### Choose Strategy
Multi-stage builds reduce final image size by 50-90%:
```dockerfile
# Stage 1: Build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]
```
See examples/Dockerfile.multi-stage for templates for Node.js, Python, Go, Java, and Rust.
#### Optimize Layer Caching
Order matters - place changing content last:
```dockerfile
# β
GOOD: Dependencies cached separately
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
# β BAD: Any file change invalidates cache
COPY . .
RUN npm ci
```
#### Apply Security Best Practices
```dockerfile
# Use specific versions
FROM node:18.17.1-alpine
# Run as non-root user
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
USER nodejs
# Copy with ownership
COPY --chown=nodejs:nodejs . .
```
Security checklist:
- Pin base image versions
- Use minimal base images (alpine, slim)
- Run as non-root user
- Scan for vulnerabilities
- Minimize installed packages
Phase 3: Docker Compose Setup
#### Define Services
Create docker-compose.yml:
```yaml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://db:5432/myapp
depends_on:
db:
condition: service_healthy
volumes:
- ./src:/app/src # Development hot-reload
networks:
- app-network
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: myapp
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 5s
networks:
- app-network
volumes:
postgres-data:
networks:
app-network:
```
See examples/docker-compose.yml for full-featured setup with monitoring, queues, and caching.
#### Environment Configuration
Use override files for different environments:
Development (docker-compose.override.yml):
```yaml
services:
app:
build:
target: development
volumes:
- ./src:/app/src
environment:
- NODE_ENV=development
command: npm run dev
```
Production (docker-compose.prod.yml):
```yaml
services:
app:
build:
target: production
restart: always
environment:
- NODE_ENV=production
```
Usage:
```bash
# Development (uses override automatically)
docker-compose up
# Production
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
```
Phase 4: Build and Run
#### Build Commands
```bash
# Basic build
docker build -t myapp:latest .
# Build specific stage
docker build --target production -t myapp:prod .
# Build with BuildKit (faster)
DOCKER_BUILDKIT=1 docker build -t myapp:latest .
```
#### Run Commands
```bash
# Single container
docker run -d -p 3000:3000 -e NODE_ENV=production myapp:latest
# Docker Compose
docker-compose up -d
# View logs
docker-compose logs -f app
# Execute in container
docker-compose exec app sh
# Stop and remove
docker-compose down -v
```
Phase 5: Debugging and Troubleshooting
#### Use Helper Script
The scripts/docker_helper.sh utility provides common debugging operations:
```bash
# Check container health
./scripts/docker_helper.sh health myapp
# Inspect details
./scripts/docker_helper.sh inspect myapp
# View logs
./scripts/docker_helper.sh logs myapp 200
# Open shell
./scripts/docker_helper.sh shell myapp
# Analyze image size
./scripts/docker_helper.sh size myapp:latest
# Cleanup resources
./scripts/docker_helper.sh cleanup
```
#### Common Issues
Container exits immediately:
```bash
docker logs myapp
docker run -it --entrypoint sh myapp:latest
```
Network connectivity:
```bash
docker network inspect myapp_default
docker exec myapp ping db
```
Volume permissions:
```bash
# Fix in Dockerfile
RUN chown -R nodejs:nodejs /app/data
```
Phase 6: Optimization
#### Reduce Image Size
Strategies:
- Use smaller base images (alpine > slim > debian)
- Multi-stage builds to exclude build tools
- Combine RUN commands for fewer layers
- Clean up in same layer
- Use .dockerignore
Example:
```dockerfile
# β
GOOD: Combined, cleaned up
RUN apt-get update && \
apt-get install -y --no-install-recommends package1 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
```
#### Build Performance
```bash
# Enable BuildKit
export DOCKER_BUILDKIT=1
# Use cache mounts
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
# Parallel builds
docker-compose build --parallel
```
Phase 7: Production Deployment
#### Production Dockerfile
```dockerfile
FROM node:18-alpine AS production
# Security: non-root user
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
WORKDIR /app
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
USER nodejs
# Health check
HEALTHCHECK --interval=30s --timeout=3s \
CMD node healthcheck.js
EXPOSE 3000
CMD ["node", "dist/index.js"]
```
#### Deployment Commands
```bash
# Tag for registry
docker tag myapp:latest registry.example.com/myapp:v1.0.0
# Push to registry
docker push registry.example.com/myapp:v1.0.0
# Deploy
docker-compose pull && docker-compose up -d
# Rolling update
docker-compose up -d --no-deps --build app
```