Configuring Blue-Green Deployment for Web Applications
Blue-Green deployment is a zero-downtime deployment strategy with two identical production environments. At any moment, only one receives traffic. The new version is deployed to the "cold" environment, tested, then traffic switches instantly.
How It Works
┌─────────────────┐
Users → │ Load Balancer │
└────────┬────────┘
│
┌───────────┴───────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Blue (v1.0) │ ← │ Green (v1.1) │
│ ACTIVE │ ←── │ STANDBY │
└──────────────┘ └──────────────┘
After switching:
┌──────────────┐ ┌──────────────┐
│ Blue (v1.0) │ │ Green (v1.1) │
│ STANDBY │ ──→ │ ACTIVE │
└──────────────┘ └──────────────┘
Implementation via Nginx
# /etc/nginx/conf.d/upstream.conf
upstream blue {
server 10.0.0.10:8080;
}
upstream green {
server 10.0.0.11:8080;
}
# Symlink points to active environment
# /etc/nginx/conf.d/active → blue.conf or green.conf
# /etc/nginx/conf.d/blue.conf
upstream active {
server 10.0.0.10:8080;
}
# /etc/nginx/conf.d/myapp.conf
server {
listen 80;
location / {
proxy_pass http://active;
}
}
# Switch script
#!/bin/bash
CURRENT=$(readlink /etc/nginx/conf.d/active.conf | grep -o 'blue\|green')
TARGET=$([ "$CURRENT" = "blue" ] && echo "green" || echo "blue")
echo "Switching from $CURRENT to $TARGET"
# Switch symlink
ln -sfn /etc/nginx/conf.d/${TARGET}.conf /etc/nginx/conf.d/active.conf
# Reload Nginx (no downtime)
nginx -t && nginx -s reload
echo "Traffic now flowing to $TARGET"
Blue-Green on AWS with ALB
# boto3 — switch Target Groups
import boto3
elbv2 = boto3.client('elbv2', region_name='eu-west-1')
def switch_traffic(listener_arn: str, target_blue: str, target_green: str):
listener = elbv2.describe_listeners(ListenerArns=[listener_arn])
current_action = listener['Listeners'][0]['DefaultActions'][0]
current_tg = current_action['TargetGroupArn']
# Determine which is active
new_tg = target_green if current_tg == target_blue else target_blue
environment = 'green' if new_tg == target_green else 'blue'
# Switch
elbv2.modify_listener(
ListenerArn=listener_arn,
DefaultActions=[{
'Type': 'forward',
'TargetGroupArn': new_tg,
}]
)
print(f"Traffic switched to {environment} ({new_tg})")
Blue-Green in Docker Swarm
#!/bin/bash
SERVICE=myapp
REGISTRY=registry.example.com
NEW_IMAGE=$REGISTRY/myapp:$BUILD_TAG
# Determine current slot
CURRENT_SLOT=$(docker service inspect $SERVICE --format '{{index .Spec.Labels "slot"}}')
NEW_SLOT=$([ "$CURRENT_SLOT" = "blue" ] && echo "green" || echo "blue")
# Start new version
docker service create \
--name "${SERVICE}-${NEW_SLOT}" \
--label slot=$NEW_SLOT \
--network myapp-network \
--replicas 2 \
$NEW_IMAGE
# Wait for readiness
echo "Waiting for $NEW_SLOT to be ready..."
until docker service ls --filter "name=${SERVICE}-${NEW_SLOT}" --format "{{.Replicas}}" | grep -q "2/2"; do
sleep 2
done
# Health check
HEALTH=$(curl -sf https://green.internal.example.com/health && echo "ok" || echo "fail")
if [ "$HEALTH" = "fail" ]; then
echo "Health check failed, aborting"
docker service rm "${SERVICE}-${NEW_SLOT}"
exit 1
fi
# Switch traffic
./switch-nginx.sh $NEW_SLOT
# Remove old environment after 30 seconds
sleep 30
docker service rm "${SERVICE}-${CURRENT_SLOT}"
Blue-Green in Kubernetes
# Two Deployments — blue and green
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-green
labels:
app: myapp
slot: green
spec:
replicas: 3
selector:
matchLabels: { app: myapp, slot: green }
template:
metadata:
labels: { app: myapp, slot: green }
spec:
containers:
- name: myapp
image: registry.example.com/myapp:v1.1.0
# Switch traffic in k8s
kubectl patch service myapp-svc \
-p '{"spec":{"selector":{"app":"myapp","slot":"green"}}}'
# Verify
kubectl rollout status deployment/myapp-green
# Rollback
kubectl patch service myapp-svc \
-p '{"spec":{"selector":{"app":"myapp","slot":"blue"}}}'
Pipeline with Blue-Green
# GitHub Actions
deploy-green:
needs: [test]
steps:
- name: Deploy to Green
run: docker stack deploy -c docker-compose.green.yml myapp-green
- name: Health Check
run: |
for i in $(seq 1 30); do
curl -sf https://green.internal/health && exit 0
sleep 2
done
exit 1
- name: Switch Traffic
run: ./switch-traffic.sh green
- name: Cleanup Blue (after 5 min)
run: sleep 300 && docker service rm myapp-blue
Implementation Timeline
- Nginx Blue-Green on VPS: 2–3 days
- AWS ALB + Target Groups: 3–4 days
- Kubernetes Blue-Green: 3–5 days







