14.3.3.1 Blue Green Parallel Env
A focused guide to Blue Green Parallel Env, connecting core concepts with practical Docker and container operations.
A blue-green parallel environment setup is the underlying infrastructure isolation that makes blue-green deployment possible: two complete, simultaneously running copies of an application's full stack, kept genuinely independent of each other at the network, naming, and resource level, so that deploying into one can never accidentally affect the other.
Naming and project isolation in Compose
The most direct way to keep two parallel environments from colliding is giving each its own Compose project name, which scopes every container, network, and volume name to that project, preventing any overlap even though both environments are built from the identical base Compose file:
docker compose -p myapp-blue -f docker-compose.yml up -d
docker compose -p myapp-green -f docker-compose.yml up -d
docker ps --filter "label=com.docker.compose.project=myapp-blue"
docker ps --filter "label=com.docker.compose.project=myapp-green"
Without distinct project names, attempting to run two copies of the same Compose file simultaneously would produce naming conflicts, since Compose by default derives container and network names from the project name combined with the service name.
Network isolation between the two environments
Each environment needs its own internal network, so that a service in the blue environment cannot inadvertently resolve or connect to a same-named service in the green environment:
networks:
internal:
name: myapp-blue-internal
networks:
internal:
name: myapp-green-internal
Explicitly naming each environment's network, rather than relying on Compose's automatic project-prefixed naming alone, makes the isolation visible and verifiable directly through docker network ls, which is useful when diagnosing whether the two environments are genuinely separated as intended.
Separate volumes prevent data cross-contamination
Each parallel environment needs its own volumes, distinct from the other environment's, so that data written by the green environment during validation never appears in the blue environment's database or vice versa:
docker volume ls --filter "label=com.docker.compose.project=myapp-blue"
docker volume ls --filter "label=com.docker.compose.project=myapp-green"
This separation is what makes it safe to run real validation traffic, including writes, against the idle environment without any risk of that validation data leaking into the live environment's actual production data.
Distinguishing shared infrastructure from per-environment infrastructure
Not everything needs to be duplicated between the two environments; a shared external database used by both, for instance, is a deliberate architectural decision distinct from duplicating internal application services:
services:
api:
environment:
- DATABASE_URL=postgres://shared-db.internal:5432/app
When a database is intentionally shared between both environments rather than duplicated, the backward-compatibility discipline around schema changes becomes essential, since both the blue and green application code need to function correctly against whatever the shared database currently looks like.
Resource allocation for two simultaneous environments
Because both environments are capable of running simultaneously, the host or cluster needs enough spare capacity to run both at the production-equivalent scale at least temporarily, even though only one is receiving live traffic at any given moment:
services:
api:
deploy:
resources:
limits:
memory: 1G
cpus: "1"
A common cost-reduction approach is keeping the idle environment scaled down to a minimal footprint between deployments, and scaling it up to full production capacity only during the deployment and validation window immediately before a cutover.
docker compose -p myapp-green up -d --scale api=1
# during deployment validation:
docker compose -p myapp-green up -d --scale api=4
DNS and internal service discovery
Within each parallel environment, services should resolve each other using names scoped to that environment, which Compose's project-based networking provides automatically, rather than relying on a shared, ambiguous naming scheme that could resolve to either environment's services depending on which network a lookup happens to traverse:
docker exec myapp-green-api-1 getent hosts db
Verifying that a service inside one environment resolves only to that same environment's dependencies, and has no network path to the other environment's services at all, is a useful and concrete way to confirm the parallel environments are genuinely isolated rather than only nominally separate.
Routing traffic to the correct parallel environment
The proxy or load balancer sitting in front of both environments is the only component that needs awareness of both, and its configuration is what determines which environment is currently "live" from an external perspective:
upstream backend {
server myapp-green-api-1:3000;
}
Everything internal to each environment remains unaware of the other; only the proxy's upstream configuration encodes which environment is currently receiving real traffic, which keeps the cutover and rollback operations simple, fast, single-point changes.
Verifying isolation before relying on it
Before trusting a parallel environment setup for a real deployment, it is worth deliberately testing that the isolation holds: writing data in one environment and confirming it does not appear in the other, and confirming network connectivity genuinely does not cross between them:
docker exec myapp-blue-api-1 ping -c 1 myapp-green-db-1
A successful ping here would indicate the two environments are not as isolated as intended, since it implies a network path exists between containers that should have no reason to reach each other.
Common mistakes
- Running two copies of the same Compose file without distinct project names, causing container and network naming collisions.
- Assuming Compose's automatic project-scoped naming alone is sufficient isolation without explicitly verifying that no network path exists between the two environments.
- Sharing volumes between the two environments unintentionally, allowing validation activity in the idle environment to contaminate the live environment's data.
- Provisioning the idle environment at a much smaller scale than production and never scaling it up before validation, producing a misleadingly easy validation pass that does not reflect real production load.
- Letting the proxy configuration become the only place where it is documented which environment is currently live, with no other record of the deployment history.
A blue-green parallel environment setup only delivers the safety blue-green deployment promises if the two environments are genuinely, verifiably isolated at the network, naming, and volume level, with the proxy as the single, deliberate point of coupling between them that determines which one is currently serving real traffic.