Multi-Service vs Separate Containers
Multi-Service vs Separate Containers
Guide for choosing between Cbox's multi-service containers (PHP-FPM + Nginx together) and separate single-process containers.
Quick Decision Guide
| Scenario | Recommendation |
|---|---|
| Simple deployment | Multi-service |
| Docker Compose | Multi-service |
| Single server | Multi-service |
| Kubernetes | Separate (usually) |
| Independent scaling | Separate |
| Microservices architecture | Separate |
| Enterprise/compliance | Separate |
Architecture Comparison
Multi-Service Container
┌─────────────────────────────────────┐
│ Single Container │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ PHP-FPM │ │ Nginx │ │
│ │ :9000 │ │ :80 │ │
│ └─────────────┘ └─────────────┘ │
│ └──── FastCGI ────┘ │
└─────────────────────────────────────┘
# docker-compose.yml
services:
app:
image: ghcr.io/cboxdk/php-baseimages/php-fpm-nginx:8.4-bookworm
ports:
- "80:80"
volumes:
- ./:/var/www/html
Separate Containers
┌─────────────────┐ ┌─────────────────┐
│ PHP-FPM │ │ Nginx │
│ Container │◄──│ Container │
│ :9000 │ │ :80 │
└─────────────────┘ └─────────────────┘
└──────── FastCGI ────────┘
# docker-compose.yml
services:
php-fpm:
image: ghcr.io/cboxdk/php-baseimages/php-fpm:8.4-bookworm
volumes:
- ./:/var/www/html
nginx:
image: ghcr.io/cboxdk/php-baseimages/nginx:bookworm
ports:
- "80:80"
volumes:
- ./:/var/www/html:ro
depends_on:
- php-fpm
Feature Comparison
| Feature | Multi-Service | Separate |
|---|---|---|
| Simplicity | Simpler | More complex |
| Resource Efficiency | Better (shared memory) | Higher overhead |
| Scaling | Scale together | Scale independently |
| Failure Isolation | Shared fate | Independent |
| Debugging | Easier | More tools needed |
| 12-Factor Compliance | Partial | Full |
| Kubernetes Native | Works | Preferred |
| Zero-Downtime Deploy | Harder | Easier |
Multi-Service: Detailed Analysis
Advantages
1. Simplicity
- Single image to manage
- One container to deploy
- Simpler docker-compose files
- Easier local development
2. Resource Efficiency
- Shared filesystem cache
- Lower memory footprint
- No network overhead between processes
- Faster FastCGI communication (localhost)
3. Easy Coordination
- Graceful shutdown handled together
- Health checks cover both processes
- Single logging stream (optional)
- Framework auto-detection works seamlessly
4. Perfect for Small Teams
- Less infrastructure to manage
- Faster deployments
- Simpler monitoring
- Lower cloud costs
Disadvantages
1. Scaling Limitations
- Can't scale PHP-FPM independently of Nginx
- Must scale both even if only one needs it
- Less efficient for high-traffic scenarios
2. Deployment Complexity
- Both processes restart together
- Harder to do rolling updates
- Connection draining more complex
3. Not "Pure" Containers
- Violates one-process-per-container guideline
- Some orchestration tools expect single process
- May conflict with enterprise policies
When to Use Multi-Service
✅ Perfect for:
- Local development
- Simple production deployments
- Docker Compose setups
- Small to medium applications
- Teams without dedicated DevOps
- Cost-sensitive environments
❌ Avoid when:
- Running in Kubernetes at scale
- Need independent scaling
- Enterprise compliance requirements
- Microservices architecture
Separate Containers: Detailed Analysis
Advantages
1. Independent Scaling
# Scale PHP-FPM independently
services:
php-fpm:
deploy:
replicas: 5 # More PHP workers
nginx:
deploy:
replicas: 2 # Fewer Nginx instances
2. Fault Isolation
- PHP crash doesn't affect Nginx
- Can restart services independently
- Better failure recovery
3. 12-Factor Compliance
- One process per container
- Treats backing services properly
- Easier to reason about
4. Kubernetes Native
# Kubernetes: Separate pods for each service
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-fpm
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
5. Zero-Downtime Deployments
- Rolling updates per service
- Canary deployments easier
- Blue-green deployments simpler
Disadvantages
1. Complexity
- More containers to manage
- Network configuration needed
- Service discovery required
- More YAML to maintain
2. Higher Resource Usage
- Two container runtimes
- Network overhead for FastCGI
- Duplicate health checks
3. Shared Volume Challenges
# Both containers need access to the same files
volumes:
app-code:
driver: local
services:
php-fpm:
volumes:
- app-code:/var/www/html
nginx:
volumes:
- app-code:/var/www/html:ro
When to Use Separate Containers
✅ Perfect for:
- Kubernetes production
- High-traffic applications
- Microservices architecture
- Independent scaling needs
- Enterprise environments
- Teams with DevOps experience
❌ Avoid when:
- Simple deployments
- Small applications
- Limited DevOps resources
- Local development (unless mirroring prod)
Migration Guide
Multi-Service → Separate
Step 1: Extract Configuration
# From multi-service container
docker exec myapp cat /etc/nginx/conf.d/default.conf > nginx.conf
docker exec myapp cat /usr/local/etc/php/conf.d/99-custom.ini > php.ini
Step 2: Update docker-compose.yml
# Before (multi-service)
services:
app:
image: ghcr.io/cboxdk/php-baseimages/php-fpm-nginx:8.4-bookworm
# After (separate)
services:
php-fpm:
image: ghcr.io/cboxdk/php-baseimages/php-fpm:8.4-bookworm
volumes:
- ./:/var/www/html
- ./php.ini:/usr/local/etc/php/conf.d/99-custom.ini
nginx:
image: ghcr.io/cboxdk/php-baseimages/nginx:bookworm
ports:
- "80:80"
volumes:
- ./:/var/www/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php-fpm
Step 3: Update Nginx Configuration
# Change FastCGI pass from localhost to service name
upstream php-fpm {
server php-fpm:9000;
}
server {
location ~ \.php$ {
fastcgi_pass php-fpm;
# ... rest of config
}
}
Separate → Multi-Service
Step 1: Consolidate Configuration
Merge Nginx and PHP configurations into the multi-service setup.
Step 2: Update docker-compose.yml
# Before (separate)
services:
php-fpm:
image: ghcr.io/cboxdk/php-baseimages/php-fpm:8.4-bookworm
nginx:
image: ghcr.io/cboxdk/php-baseimages/nginx:bookworm
# After (multi-service)
services:
app:
image: ghcr.io/cboxdk/php-baseimages/php-fpm-nginx:8.4-bookworm
ports:
- "80:80"
volumes:
- ./:/var/www/html
Step 3: Remove Network Configuration
FastCGI now uses localhost automatically.
Kubernetes Patterns
Multi-Service in Kubernetes
Still works, just not "native":
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: ghcr.io/cboxdk/php-baseimages/php-fpm-nginx:8.4-bookworm
ports:
- containerPort: 80
Separate in Kubernetes (Sidecar Pattern)
PHP-FPM as sidecar in same pod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
template:
spec:
containers:
- name: nginx
image: ghcr.io/cboxdk/php-baseimages/nginx:bookworm
ports:
- containerPort: 80
volumeMounts:
- name: app-code
mountPath: /var/www/html
readOnly: true
- name: php-fpm
image: ghcr.io/cboxdk/php-baseimages/php-fpm:8.4-bookworm
ports:
- containerPort: 9000
volumeMounts:
- name: app-code
mountPath: /var/www/html
volumes:
- name: app-code
emptyDir: {}
Separate in Kubernetes (Full Separation)
Different deployments entirely:
# php-fpm-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-fpm
spec:
replicas: 5 # Scale PHP independently
template:
spec:
containers:
- name: php-fpm
image: ghcr.io/cboxdk/php-baseimages/php-fpm:8.4-bookworm
---
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2 # Scale Nginx independently
template:
spec:
containers:
- name: nginx
image: ghcr.io/cboxdk/php-baseimages/nginx:bookworm
Performance Comparison
Latency
| Setup | Avg Latency | Notes |
|---|---|---|
| Multi-service | ~1ms | Localhost FastCGI |
| Separate (same pod) | ~1-2ms | Localhost FastCGI |
| Separate (diff pods) | ~2-5ms | Network FastCGI |
Memory Usage
| Setup | Memory (per replica) |
|---|---|
| Multi-service | ~80-120MB |
| Separate (combined) | ~100-150MB |
Throughput
For most applications, both approaches handle similar throughput. Separate containers excel when:
- PHP processing is the bottleneck (scale PHP-FPM only)
- Static assets dominate (scale Nginx only)
Decision Matrix
Score each factor 1-5 for your project, multiply by weight:
| Factor | Weight | Multi-Service | Separate |
|---|---|---|---|
| Simplicity | 3 | 5 | 2 |
| Scaling Flexibility | 2 | 2 | 5 |
| Resource Efficiency | 2 | 4 | 3 |
| Kubernetes Native | 2 | 3 | 5 |
| Debugging Ease | 1 | 4 | 3 |
Typical Scores:
- Small/Medium Projects: Multi-service wins
- Large/Enterprise: Separate wins
Need more guidance? Getting Started | Production Deployment