Operations 8 min read

Implementing Gray Release with Nginx, Docker, and NestJS

This guide explains how to set up a gray‑release (canary) deployment using Nginx as a reverse‑proxy gateway, Docker containers for isolation, and two versions of a NestJS service, with traffic split controlled by cookies and configurable percentages.

IT Services Circle
IT Services Circle
IT Services Circle
Implementing Gray Release with Nginx, Docker, and NestJS

Software releases are usually iterative, and new versions are tested with a gray‑release system that can route a portion of traffic to the new code while keeping the rest on the stable version, reducing the impact of potential bugs.

We first create two versions of a NestJS application. The first version is generated with:

npx nest new gray_test -p npm

and started using:

npm run start

After confirming the service runs (you should see a "Hello World" response), we modify the AppService and the listening port to obtain a second version.

Next, we run two Nginx containers to act as the gateway layer. Using Docker Desktop we pull the official Nginx image and start the first container named gray1 mapping host port 82 to container port 80 . The container is then copied to the host:

docker cp gray1:/etc/nginx/conf.d ~/nginx-config

We edit the copied default.conf to add a location block that rewrites /api/ requests and proxies them to the Nest service:

location ^~ /api {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://192.168.1.6:3001;
}

A second Nginx container ( gray2 ) is started with host port 83 mapped to 80 and the local ~/nginx-config directory mounted to /etc/nginx/conf.d inside the container, ensuring the configuration changes are reflected instantly.

To enable traffic splitting, we define multiple upstream groups in the Nginx config:

upstream version1.0_server {
    server 192.168.1.6:3000;
}

upstream version2.0_server {
    server 192.168.1.6:3001;
}

upstream default {
    server 192.168.1.6:3000;
}

Routing is then decided based on a cookie named version :

set $group "default";
if ($http_cookie ~* "version=1.0") {
    set $group version1.0_server;
}
if ($http_cookie ~* "version=2.0") {
    set $group version2.0_server;
}

location ^~ /api {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://$group;
}

When a request arrives, Nginx checks the cookie and forwards the request to the corresponding upstream, achieving gray‑release behavior. By adjusting the proportion of users that receive different version cookies (e.g., 80% get 1.0 , 20% get 2.0 ), you can gradually roll out new features or run A/B experiments.

The complete flow is: first request → traffic‑coloring service sets a version cookie according to the configured ratio → subsequent requests are routed by Nginx based on that cookie, allowing safe, incremental deployment and product testing.

In summary, Nginx’s reverse‑proxy capabilities combined with Docker isolation and simple cookie‑based routing provide a lightweight yet powerful gray‑release solution for backend services.

backendDockerAB testingoperationsgray releasenginxTraffic Splitting
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.