Back to Articles
DevOps

Zero-Downtime Deploys with Docker and Nginx

June 22, 20257 min read

Taking down your API to ship a new version is acceptable at 3 AM with three users. In production, it's not. Here's a deployment pattern I've used that achieves zero downtime with nothing more than Docker, Nginx, and a short script.

The two-upstream trick

Run two instances of your app behind Nginx — app-blue and app-green. At any time, one is live and the other is idle. A deploy spins up the idle one, waits for it to be healthy, then flips Nginx's upstream.

upstream app_live {
  server app-blue:3000;
}

server {
  location / {
    proxy_pass http://app_live;
    proxy_set_header Host $host;
  }
}

Health checks before the switch

Never flip the upstream until the new container passes a health check. A simple /health endpoint returning 200 OK after the app boots is enough:

until curl -sf http://localhost:3001/health; do
  echo "waiting..."
  sleep 1
done

The sequence

  1. Build the new image.
  2. Start it on the idle port.
  3. Poll /health until it responds.
  4. Update Nginx upstream to point at the new container.
  5. Reload Nginx (nginx -s reload — no dropped connections).
  6. Stop the old container.

What about rollbacks?

Because the previous container is still defined, a rollback is just flipping the upstream back. You can be back online in seconds.

The beauty of this approach is its simplicity — no Kubernetes, no service mesh, just containers and a reverse proxy doing what they do best.

Thanks for reading. Browse more articles →