Skip to content
Go back

Docker Network Aliases: The Feature Nobody Uses

By SumGuy 5 min read
Docker Network Aliases: The Feature Nobody Uses

Most Docker developers know about networks. You create one, attach containers, they talk via container name. Simple. But there’s a hidden feature that makes blue-green deploys, rolling updates, and service discovery patterns trivial: network aliases.

Network aliases let a single container have multiple DNS names on the same network. You can use them to swap implementations without changing your app’s config.

The Problem They Solve

Imagine you have two versions of a database service: postgres-v1 and postgres-v2. Your app talks to them via hostname. You want to switch from v1 to v2 without changing the app’s connection string.

Normally, you’d have to:

  1. Update the app config to point to postgres-v2
  2. Redeploy the app
  3. Risk downtime or bugs

With aliases, you can:

  1. Start postgres-v2 with an alias of postgres
  2. Connections automatically route to v2
  3. No app config change needed

How Aliases Work

When you create a Docker network, the embedded DNS server tracks all connected containers. By default, it knows them by their container name. Aliases register additional names pointing to the same container.

Here’s the basic syntax:

Terminal window
$ docker network create mynet
$ docker run --name db-v1 \
--network mynet \
--network-alias postgres \
postgres:15

Now the container db-v1 is reachable as both db-v1 and postgres. Any container on mynet that resolves postgres gets the IP of db-v1.

Blue-Green Deploy Example

Here’s the real power. Suppose you’re running a production setup:

Terminal window
$ docker network create app-net
# Green deployment (current)
$ docker run -d --name api-green \
--network app-net \
--network-alias api \
myapp:v1.2.3
# Frontend connects to 'api' (resolves to api-green)
$ docker run -d --name frontend \
--network app-net \
-e API_HOST=api \
myfrontend:latest

Now you want to deploy a new version. Start it as blue:

Terminal window
# Blue deployment (new)
$ docker run -d --name api-blue \
--network app-net \
myapp:v2.0.0
# At this point, frontend still talks to green
# Everything works, no downtime

Once blue is healthy and tested, flip the alias:

Terminal window
# Remove the alias from green
$ docker network disconnect mynet api-green
$ docker run -d --name api-green-v1.2.3 \
--network app-net \
myapp:v1.2.3
# Add the alias to blue
$ docker run -d --name api-blue \
--network app-net \
--network-alias api \
myapp:v2.0.0

Now api resolves to api-blue. Frontend keeps the same config, but talks to v2. Zero downtime, instant rollback (flip back to green).

Docker Compose Example

In Compose, you define aliases in the service definition:

docker-compose.yml
version: '3.8'
services:
postgres-v1:
image: postgres:14
networks:
app-net:
aliases:
- db # Can resolve as 'db'
- postgres-primary
api:
image: myapp:latest
depends_on:
- postgres-v1
environment:
DATABASE_URL: postgresql://postgres:5432/mydb
networks:
- app-net
networks:
app-net:

The api service can connect to postgres-v1 via the hostname db. If you later swap in postgres-v2 with the same aliases, no app changes needed.

Real-World Use Case: Canary Deployments

Here’s how a smart team uses aliases for canary deployments:

Terminal window
$ docker network create prod-net
# Stable release: 99% of traffic
$ docker run -d --name api-prod-v1.5 \
--network prod-net \
--network-alias api-stable \
myapp:v1.5
# Canary: 1% of traffic
$ docker run -d --name api-canary-v2.0 \
--network prod-net \
--network-alias api-canary \
myapp:v2.0
# Load balancer routes most requests to 'api-stable',
# a small percentage to 'api-canary'
$ docker run -d --name lb \
--network prod-net \
-p 80:8080 \
my-load-balancer

Your load balancer knows about both aliases. It routes based on policy, gradually shifting traffic to the canary. If the canary has issues, you never promoted it to api-stable.

Practical Multi-Database Example

Here’s a more complex setup: a database migration scenario.

docker-compose.yml
version: '3.8'
services:
# Old database (being phased out)
mysql-legacy:
image: mysql:5.7
networks:
app-net:
aliases:
- db-read # Backward compatible name
environment:
MYSQL_ROOT_PASSWORD: secret
# New database (replacing mysql)
postgres-new:
image: postgres:15
networks:
app-net:
aliases:
- db-write # New name, but app will use it
environment:
POSTGRES_PASSWORD: secret
# App uses 'db-read' and 'db-write'
app:
build: .
depends_on:
- mysql-legacy
- postgres-new
environment:
READ_DB_HOST: db-read
WRITE_DB_HOST: db-write
networks:
- app-net
networks:
app-net:

As you migrate read queries to postgres, you just change which service has the db-read alias. No app code change.

Limitations and Gotchas

  1. Aliases only work on custom networks: Bridge (default) and host networks don’t support aliases. You need to explicitly docker network create.

  2. DNS isn’t load-balanced: If two containers have the same alias, DNS round-robins between them. This can surprise people.

  3. Aliases are per-network: A container can have different aliases on different networks.

  4. No layer 7 routing: Aliases resolve at DNS level. If you need smart routing (URL path, headers), use a load balancer.

Quick Checklist

Aliases are underrated. They’re simple, powerful, and solve real deployment problems. Most teams don’t use them and end up redeploying apps for zero-downtime updates. Don’t be that team.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it may appear here.


Previous Post
The umask You've Been Ignoring
Next Post
/proc as a Debugging Tool

Related Posts