iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

DNS & Service Names

Docker links were the original way to make container A reach container B by name. They are legacy now — modern Docker uses user-defined networks and the embedded DNS server, which gives you the same name-based discovery without legacys footguns (transitive dependencies, alias drift, fragile environment variables).

User-defined networks, embedded DNS, aliases

EXAMPLE
# 1) Create a user-defined bridge network
docker network create shop-net

# 2) Run containers on it — they reach each other by NAME (auto-registered DNS)
docker run -d --name db    --network shop-net postgres:16
docker run -d --name redis --network shop-net redis:7
docker run -d --name api   --network shop-net \
  -e DATABASE_URL=postgres://postgres@db:5432/shop \
  -e REDIS_URL=redis://redis:6379 \
  my/api:1.0

# 'db' and 'redis' resolve via Dockers embedded DNS at 127.0.0.11. No /etc/hosts hacks.

# 3) Aliases — give a container an extra DNS name on a network
docker network connect --alias primary shop-net db

# Now 'db' AND 'primary' both resolve to the postgres container.

# 4) Multiple networks for segmentation (web tier vs internal tier)
docker network create web-net    --driver bridge
docker network create internal   --driver bridge --internal   # NO external internet

docker run -d --name lb        --network web-net    -p 80:80 nginx
docker run -d --name api       --network web-net   --network-alias api my/api:1.0
docker network connect internal api     # api ALSO sits on internal
docker run -d --name db        --network internal postgres:16

# api can reach db (both on 'internal'), and the LB can reach api (both on 'web-net'),
# but db has no path to the public internet.

# 5) Inspect what is on a network
docker network inspect shop-net --format \
  '{{range $k, $v := .Containers}}{{ $v.Name }}: {{ $v.IPv4Address }}\n{{end}}'

# 6) Compose: networks are the default mechanism, links should not appear
# docker-compose.yml
# services:
#   api:
#     image: my/api:1.0
#     networks: [web, internal]
#     environment:
#       DATABASE_URL: postgres://postgres@db:5432/shop
#   db:
#     image: postgres:16
#     networks: [internal]
#   lb:
#     image: nginx
#     networks: [web]
#     ports: ['80:80']
# networks:
#   web: {}
#   internal:
#     internal: true

# 7) DO NOT use legacy --link any more
# docker run --link db:database ...   # deprecated; only works on the default bridge
# It populates env vars (DB_PORT_5432_TCP=...) and /etc/hosts entries that go stale.

# 8) External DNS records inside a container
# Add --dns 1.1.1.1 --dns 8.8.8.8 if your hosts resolv.conf is unusable.
docker run --rm --dns 1.1.1.1 alpine nslookup example.com

Why it matters

Default to a user-defined bridge network for any project with more than one container. Container name = DNS name is the whole feature, and it removes a class of bugs (link order, restart races) that legacy --link papered over only some of the time.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
# Inside a network, containers reach each other by name.
# From api: connect to host 'db'.
Try it Yourself »

Discussion

Loading…