Mahamudul Hasan Rubel
HomeAboutProjectsSkillsExperienceBlogPhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • About
  • Projects
  • Skills
  • Experience
  • Blog
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
DevOpsJune 21, 20264 min read

Blue-Green Deployment for VPS: Managing Traffic with Traefik

Master blue-green deployment on a single VPS using Docker Compose and Traefik. Achieve zero-downtime releases without the complexity of Kubernetes clusters.

DevOpsDockerTraefikVPSDeploymentLinuxCI/CD
Close-up of a green traffic light against a clear blue sky, symbolizing go and safety.

When you're running a side project or a small production app on a single $5 VPS, you eventually hit the "maintenance window" problem. Pushing a new container version usually means stopping the old one, leading to a few seconds of 502 Bad Gateway errors. While I’ve covered deploying a side project on a single cheap VPS reliably before, simple restarts aren't enough for applications that need high availability.

I recently moved my primary stack to a blue-green model using Traefik and Docker Compose. It’s significantly lighter than a full Kubernetes setup, yet it provides the same peace of mind during deployments.

Why Blue-Green Deployment Matters

A blue-green deployment works by running two identical production environments. At any time, only one (the "Blue" environment) is live. When you deploy, you spin up the new version in the "Green" environment, verify it’s healthy, and then tell your reverse proxy to route all traffic to Green. If something goes sideways, you point the proxy back to Blue instantly.

I’ve found this approach is roughly 1.5x faster to roll back than traditional redeploys. You aren't "deploying" a fix during an outage; you're just flipping a switch.

Setting Up Your Traefik Infrastructure

Various tangled wires connected to system near black metal cases in server room

To pull this off, you need a stable Traefik instance running as a separate service, outside the lifecycle of your application containers. I keep mine in a dedicated proxy directory with a simple docker-compose.yml.

YAML
version: '3.8'
services:
  traefik:
    image: traefik:v2.10
    command: --providers.docker=true --entrypoints.web.address=:80
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

The magic happens in how you label your application containers. Instead of hardcoding a single service, you define two separate docker-compose projects—app-blue and app-green—that share the same entry point.

Orchestrating Traffic with Traefik Labels

You don't need fancy service mesh tools. Traefik’s dynamic configuration is enough to handle the switch. In your app's docker-compose.yml, define the labels dynamically based on the current active color.

YAML
services:
  web:
    image: my-app:v2.0.0
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.myapp.rule=Host(`myapp.com`)"
      - "traefik.http.routers.myapp.service=myapp-${COLOR}"
      - "traefik.http.services.myapp-${COLOR}.loadbalancer.server.port=8080"

When you deploy, you set an environment variable COLOR=green. Traefik sees the new service, registers it, and starts sending traffic to it. Because Traefik handles the routing table in memory, the switch is atomic.

The Deployment Workflow

I use a simple shell script to coordinate the switch. It follows a three-step dance:

  1. Spin up the idle environment: If Blue is live, deploy Green.
  2. Health check: Use curl to verify the new container responds with a 200 OK.
  3. Switch traffic: Update the active label or the Traefik dynamic config file.

I used to manually update environment variables, which led to about two separate human errors in a single month. Now, I use a small CI script that queries the current active container using docker inspect before deciding which color to deploy.

If you are already using CI/CD, you can easily integrate this into a zero-downtime deploy with GitHub Actions. The logic remains the same: treat your infrastructure as a state machine where the "active" state is just a label in your proxy.

Common Pitfalls

The biggest "gotcha" isn't the traffic switching—it's the database. If your new version (Green) requires a database schema change that breaks the old version (Blue), your rollback path is destroyed.

I’ve learned the hard way that schema migrations must be backward compatible. Always add columns first, migrate data in a second step, and remove old columns only after the new version has been stable for a few days. If you're doing complex migrations, you might want to look into how Kubernetes Canary Deployments handle progressive traffic, though that's usually overkill for a single VPS.

Frequently Asked Questions

Does this require double the RAM? Yes. You are running two copies of your application simultaneously. For small apps, this is negligible (usually under 200MB), but if you have memory-intensive background workers, you'll need to account for the overhead.

How do I handle persistent storage? If your app writes to local disk, don't use the same volume for both Blue and Green. Use versioned volumes or, better yet, offload state to an external managed database or S3-compatible storage.

Is this really better than a simple docker-compose up -d --build? A standard up -d recreates containers one by one. If you have multiple replicas, it’s fine. If you have one, you have downtime. This blue-green pattern is specifically for when you cannot afford that gap.

I’m still experimenting with automating the "cleanup" phase where the old environment is automatically killed after a successful switch. For now, I leave it running for an hour—just in case I need to roll back at 2 AM. It’s not elegant, but it works, and I’d rather have a slightly cluttered server than a broken production environment.

Back to Blog

Similar Posts

A vibrant display of love locks attached to a fence with colorful ribbons.
DevOpsJune 21, 20264 min read

WireGuard Mesh Networking: Secure Your VPS Cluster Communication

WireGuard mesh networking is the most efficient way to secure inter-node communication. Learn to build a private, encrypted VPS cluster network today.

Read more
Shipping containers and cranes at Hamburg port showcasing global trade.
DevOps
June 21, 2026
4 min read

Docker Socket Activation: Zero-Downtime Hot-Swapping with Systemd

Docker socket activation with Systemd and Nginx lets you hot-swap containers without dropping connections. Learn this robust deployment engineering strategy.

Read more
Close-up of colorful programming code on a computer screen, showcasing digital technology.
DevOpsJune 20, 20264 min read

Zero-downtime deploy with GitHub Actions: A Practical Guide

Achieve a zero-downtime deploy with GitHub Actions using blue-green strategies. Learn how to keep your services running seamlessly during every release.

Read more