By default, containers inherit DNS configuration from the Docker daemon. When you need to override that, three directives give you full control: dns:, dns_search:, and dns_opt:.

Setting custom DNS servers

dns: overrides which resolvers the container queries:

services:
  app:
    image: myapp
    dns:
      - 1.1.1.1
      - 8.8.8.8

The container now uses Cloudflare and Google DNS instead of whatever the host provides. Useful when:

  • The host DNS is slow or unreliable for your use case
  • You need a specific public DNS for content filtering (Pi-hole, NextDNS)
  • A development environment must reach internal services through a corporate DNS server

Search domains

dns_search: adds search domains so short names resolve against them:

services:
  app:
    image: myapp
    dns_search:
      - corp.example.com
      - internal.example.com

Now app can resolve database as database.corp.example.com (or database.internal.example.com) without using a fully qualified name. Convenient when working with internal services that share a parent domain.

Resolver options

dns_opt: passes options to the resolver library:

services:
  app:
    image: myapp
    dns_opt:
      - "ndots:2"
      - "timeout:1"
      - "attempts:2"

Common options:

  • ndots:N — names with fewer than N dots are looked up using search domains first
  • timeout:N — seconds to wait for a DNS response
  • attempts:N — how many retries before giving up
  • rotate — round-robin through the configured nameservers

A practical example

A development container that needs to resolve internal hostnames through a VPN’s DNS:

services:
  dev-app:
    image: myapp
    dns:
      - 10.0.0.1            # Corporate DNS reached over VPN
      - 1.1.1.1             # Public fallback
    dns_search:
      - corp.example.com
    dns_opt:
      - "ndots:1"
      - "timeout:2"

api, auth, and other internal hostnames resolve through corporate DNS via the search domain, while public DNS handles everything else.

dns vs extra_hosts

Easy to confuse, but very different:

  • dns: ([Tip #65, this one]): tells the container which DNS server(s) to query. Affects how names are resolved.
  • extra_hosts: (Tip #36): adds static entries to /etc/hosts. Bypasses DNS entirely for those specific names.

Use dns: when you want to change the resolver. Use extra_hosts when you want to pin a specific hostname to a specific IP regardless of DNS.

Verifying the configuration

Check what’s actually configured inside the container:

# See the resolved /etc/resolv.conf
docker compose exec app cat /etc/resolv.conf

# Test name resolution
docker compose exec app getent hosts api.corp.example.com

If your settings don’t appear, the Docker daemon’s default DNS may take precedence, or the image’s entrypoint may be rewriting /etc/resolv.conf.

Further reading