Zero-Downtime Blue-Green Deployments with Docker Compose and Nginx Reloads
Achieve seamless atomic application updates on a single production VPS using dual container sockets, upstream switching, and curl health validation.
Netbay Engineering
Netbay Engineering
On this page
Deploying application updates on a single Linux server often introduces a frustrating window of downtime. When 'docker compose down' executes, existing in-flight HTTP requests are dropped, new incoming TCP connections receive connection refused errors, and users see broken screens until the new containers finish booting.
You do not need an entire Kubernetes cluster to achieve zero-downtime deployments. By maintaining dual parallel container environments (Blue and Green) governed by Docker Compose and an Nginx reverse proxy, you can achieve atomic, request-safe deployments on a single VPS host.
Dual-Upstream Blue-Green Architecture
The blue-green model treats containers as disposable side-by-side color pairs:
- Active Color (Blue): Runs the current stable release on internal port 3001, receiving 100% of live traffic via Nginx.
- Idle Color (Green): Receives the new release on internal port 3002. It boots, connects to the database, executes schema checks, and undergoes local curl health verification.
- Atomic Symlink Switch: Once Green is verified healthy, the deployment script updates an Nginx upstream symlink and executes 'nginx -s reload'. Nginx gracefully hands off active connections to Green without dropping a single packet.
- Teardown: The previous Blue container is gracefully stopped after a 15-second drain window.
Docker Compose Configuration with Dual Targets
In 'docker-compose.yml', define the two target color services:
# /srv/app/docker-compose.yml
version: '3.8'
services:
app-blue:
image: registry.example.in/myapp:current
container_name: app-blue
restart: always
ports:
- "127.0.0.1:3001:3000"
environment:
- NODE_ENV=production
- COLOR=blue
app-green:
image: registry.example.in/myapp:current
container_name: app-green
restart: always
ports:
- "127.0.0.1:3002:3000"
environment:
- NODE_ENV=production
- COLOR=greenAutomated Zero-Downtime Deployment Script
Below is the complete deployment script executing container startup, health polling, and atomic symlink cutover:
#!/usr/bin/env bash
set -euo pipefail
# 1. Determine active and idle colors
if [ -f /etc/nginx/current_color ] && [ "$(cat /etc/nginx/current_color)" = "blue" ]; then
ACTIVE="blue"
IDLE="green"
IDLE_PORT="3002"
else
ACTIVE="green"
IDLE="blue"
IDLE_PORT="3001"
fi
echo "Active target: $ACTIVE | Deploying new release to: $IDLE"
# 2. Pull and start idle container
docker compose pull app-$IDLE
docker compose up -d app-$IDLE
# 3. Health check verification loop
echo "Verifying $IDLE health on port $IDLE_PORT..."
for i in {1..30}; do
if curl -fs "http://127.0.0.1:$IDLE_PORT/healthz" > /dev/null; then
echo "Health check passed!"
break
fi
sleep 1
if [ "$i" -eq 30 ]; then
echo "FATAL: Health check timed out! Aborting deployment."
docker compose stop app-$IDLE
exit 1
fi
done
# 4. Atomic Nginx upstream cutover
echo "upstream backend { server 127.0.0.1:$IDLE_PORT; }" > /etc/nginx/conf.d/upstream.conf
nginx -t && nginx -s reload
echo "$IDLE" > /etc/nginx/current_color
echo "Traffic successfully shifted to $IDLE!"
# 5. Gracefully drain and stop old container
sleep 15
docker compose stop app-$ACTIVE
echo "Zero-downtime deployment finished cleanly."Video Guide on Docker & Container Deployments
Watch this fundamental tutorial on Docker container management and deployment workflows:
Blue-green deployments give small engineering teams enterprise-grade deployment reliability without complex orchestrators.
Run high-performance container stacks with enterprise NVMe storage on Netbay Cloud VPS servers at netbayhosts.in.
Keep reading
Follow along on a real VPS
Deploy Linux in under 60 seconds
These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.
Deploy an instance