Troubleshooting Docker Compose: 'server not found' Container Name Resolution Errors
Resolve inter-container communication failures in Docker Compose due to DNS issues. Diagnose 'server not found' errors when containers can't locate each other.
When deploying multi-service applications with Docker Compose, inter-container communication relies heavily on Docker’s built-in DNS resolution. An error indicating “server not found” or “name or service not known” signals a critical failure in this name resolution process, preventing containers from locating and communicating with their dependencies. This guide will walk you through diagnosing and resolving such issues within your Docker Compose stack.
Symptom & Error Signature
The primary symptom is a service within your Docker Compose stack failing to connect to another service, typically presenting as a DNS resolution error. This can manifest in application logs, curl commands executed from within a container, or ping attempts.
# Example from inside a container attempting to reach another service
$ docker exec -it myapp_web_1 bash
root@<container_id>:/app# curl http://myservice_db:5432
curl: (6) Could not resolve host: myservice_db
# Example from application logs (e.g., Node.js, PHP, Python)
web_1 | 2026-07-04 10:30:05.123Z ERROR: Unable to connect to database.
web_1 | Error: getaddrinfo ENOTFOUND myservice_db
# or
web_1 | PHP Fatal error: Uncaught PDOException: SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo for myservice_db failed: Name or service not known
# Example from a container trying to ping another
$ docker exec -it myapp_web_1 bash
root@<container_id>:/app# ping myservice_backend
ping: myservice_backend: Name or service not known
The key indicator is Could not resolve host, ENOTFOUND, Name or service not known, or similar messages explicitly mentioning a failure to resolve the hostname of an internal Docker service.
Root Cause Analysis
The “server not found” error for inter-container communication in Docker Compose primarily stems from issues with Docker’s internal DNS resolution mechanism. Here are the most common underlying reasons:
- Incorrect Service Naming or Typo: The most frequent cause. The hostname used to reference a target container must precisely match its service name as defined in your
docker-compose.ymlfile. Docker’s internal DNS service registers each service name as an alias for its containers’ IP addresses within the Compose network. - Target Service Not Running or Healthy: If the target service (e.g.,
myservice_db) is not running, has crashed, or is stuck in an unhealthy state, Docker’s internal DNS may not have a valid IP address to resolve for that service name. - Docker Compose Network Misconfiguration:
- Services in Different Networks: If services are explicitly defined in different custom networks and not connected, they cannot resolve each other’s hostnames. By default, all services in a
docker-compose.ymlare connected to a single, implicitly created network (<projectname>_default). - Incorrect
network_mode: Usingnetwork_mode: "host"ornetwork_mode: "service:..."can bypass Docker’s internal DNS, requiring direct IP addresses or host-level DNS, which is generally not suitable for inter-container resolution by service name. - External Networks: Misconfiguration when attempting to connect to pre-existing external networks.
- Services in Different Networks: If services are explicitly defined in different custom networks and not connected, they cannot resolve each other’s hostnames. By default, all services in a
- Docker Daemon DNS Resolver Issues: Less common for inter-container resolution, but possible if the Docker daemon’s global DNS configuration (e.g., in
/etc/docker/daemon.json) is incorrect or points to an unreachable DNS server, potentially affecting how Docker itself resolves names, including internal ones or external names requested by containers. - Host Firewall Interference: While Docker typically manages its own
iptablesrules, an aggressively configured host firewall (likeufwon Ubuntu) could, in rare scenarios, interfere with traffic on Docker’s bridge networks, preventing internal DNS queries or responses. - Stale Docker State: Occasionally, Docker’s internal state, including network and DNS configurations, can become corrupted or stale, requiring a clean rebuild of the stack.
Step-by-Step Resolution
Follow these steps meticulously to diagnose and resolve the “server not found” issue.
1. Verify Service Naming Convention and docker-compose.yml Consistency
The service name defined in docker-compose.yml acts as the hostname for other services within the same Docker Compose network. Ensure that the hostname used in your application code or environment variables precisely matches the service name.
-
Inspect your
docker-compose.yml: Locate the service that is failing to connect and the service it’s trying to reach. Note their exact service names.# Example docker-compose.yml version: '3.8' services: web: build: ./web_app ports: - "80:80" environment: DATABASE_HOST: db_service # This must match the 'db_service' below DATABASE_PORT: 5432 db_service: # This is the service name acting as the hostname image: postgres:13 environment: POSTGRES_DB: mydatabase POSTGRES_USER: user POSTGRES_PASSWORD: password volumes: - db_data:/var/lib/postgresql/data volumes: db_data: -
Check Application Code/Environment Variables: Confirm that the hostname referenced within the
webservice’s application code or itsenvironmentvariables (DATABASE_HOSTin the example) exactly matchesdb_service. A common mistake is usinglocalhost, the container image name (e.g.,postgres), or a custom alias that isn’t defined.
2. Confirm All Dependent Services Are Running and Healthy
A service cannot be resolved if it’s not running or has crashed.
-
List running services: Use
docker-compose psto see the status of all services in your stack.$ docker-compose ps NAME COMMAND SERVICE STATUS PORTS myapp-web-1 "/docker-entrypoint.…" web running 0.0.0.0:80->80/tcp myapp-db_service-1 "docker-entrypoint.s…" db_service running 5432/tcpEnsure the
STATUScolumn for the target service (e.g.,db_service) showsrunningorhealthy. If it showsExitedorrestarting, you need to debug that service’s startup failure first. -
Review logs of the target service: Check the logs of the service that couldn’t be found for any startup errors.
$ docker-compose logs db_serviceLook for errors indicating why the service might not be fully operational or has exited prematurely.
3. Inspect Docker Compose Network Configuration
Docker Compose automatically creates a default network for all services. If you’re using custom networks, ensure they are correctly configured and services are attached to them.
-
Check implicit network: If no
networkssection is defined indocker-compose.yml, all services are connected to a single default bridge network named<projectname>_default(e.g.,myapp_default). Services on this network should be able to resolve each other by name. -
Review explicit network definitions: If you have a
networkssection, ensure that both the failing and the target service are explicitly assigned to the same network.# Example with explicit networks version: '3.8' services: web: build: ./web_app networks: - my_app_network # Connected to this network db_service: image: postgres:13 networks: - my_app_network # Also connected to this network networks: my_app_network: # Definition of the custom network driver: bridgeIf services are on different networks, they will not be able to resolve each other’s hostnames without additional linking or external network configuration, which is generally not recommended for simple inter-service communication.
-
Inspect running container networks: You can verify which networks a container is connected to using
docker inspect.$ docker inspect myapp-web-1 | grep -A 5 "Networks"Confirm that both containers share at least one common network.
4. Manually Test Name Resolution within a Container
This is a crucial diagnostic step to confirm if the DNS resolution issue is internal to the container or a broader Docker problem.
-
Access the failing container’s shell:
$ docker exec -it myapp-web-1 sh # or bash, depending on the container image -
Install DNS utilities (if needed): Some minimal container images might not have
ping,nslookup, ordiginstalled.# For Debian/Ubuntu-based images apt update && apt install -y iputils-ping dnsutils # For Alpine-based images apk add --no-cache iputils busybox-extras -
Attempt to
pingthe target service:# From inside the web container, ping the db_service root@<web_container_id>:/app# ping -c 3 db_serviceIf
pingfails with “Name or service not known”, it confirms the DNS resolution issue. If it resolves to an IP but still can’t connect, you might have a different issue (e.g., port or firewall). -
Use
nslookupordig: These tools provide more detail about DNS resolution.root@<web_container_id>:/app# nslookup db_service # Expected successful output: # Server: 127.0.0.11 # Address: 127.0.0.11#53 # # Name: db_service # Address: 172.18.0.2 # This IP will varyIf
nslookupreturnscan't resolve 'db_service': Name or service not known, the problem is definitively with DNS resolution. TheServer: 127.0.0.11indicates Docker’s internal DNS resolver.
5. Review Docker Daemon DNS Configuration (Advanced)
While Docker’s internal DNS for docker-compose is largely self-contained, an incorrect global Docker daemon DNS setting can sometimes interfere.
-
Check
/etc/docker/daemon.json: This file configures the Docker daemon. Look for adnskey.$ cat /etc/docker/daemon.jsonIf you see something like:
{ "dns": ["8.8.8.8", "8.8.4.4"] }and these DNS servers are unreachable or misconfigured, it might indirectly affect Docker’s internal DNS if it tries to forward queries (though less common for inter-container resolution).
[!WARNING] Do not add public DNS servers (e.g., 8.8.8.8) to
daemon.jsonunless absolutely necessary and you understand the implications. Docker’s default internal DNS is highly optimized for inter-container communication. Adding external DNS can sometimes introduce more problems than it solves for this specific issue. -
Remove or correct
dnsentries: If you havednsentries that are suspect, temporarily remove them or change them to reliable, local DNS servers (if required by your network). -
Restart Docker daemon: After modifying
daemon.json, the Docker daemon must be restarted.$ sudo systemctl restart docker
6. Check Host Firewall (UFW) Rules
On Ubuntu, ufw (Uncomplicated Firewall) is commonly used. Docker automatically manages iptables rules for its networks, but ufw can sometimes interfere.
-
Check UFW status:
$ sudo ufw statusLook for rules that might be explicitly blocking traffic on Docker’s bridge interfaces (e.g.,
docker0, or custom bridge interfaces likebr-XXXXXXXXXXXX). By default,ufwshould not block internal Docker traffic ifufwis configured to allow Docker’siptablesrules. -
Temporarily disable UFW (for testing):
[!WARNING] Disabling your host firewall can expose your system to security risks. Only do this temporarily for testing in a controlled environment and re-enable it immediately after.
$ sudo ufw disableAfter disabling, re-test your Docker Compose stack. If the issue resolves, you’ll need to configure
ufwto properly coexist with Docker. A common solution is to ensure the/etc/default/ufwfile hasDEFAULT_FORWARD_POLICY="ACCEPT"or to use specificufwrules to allow Docker traffic, though Docker’siptablesmanagement usually takes precedence.
7. Perform a Clean Stack Rebuild
If all previous steps fail, a clean rebuild of your Docker Compose stack can resolve issues caused by stale or corrupted Docker internal states, including networks and DNS caches.
-
Stop and remove the entire stack: The
--volumesflag removes any named volumes, and--remove-orphansremoves containers not defined in the currentdocker-compose.yml.[!IMPORTANT] Using
--volumeswill delete all data stored in named volumes. If you have critical data in volumes (e.g., a database), ensure you have backups or omit--volumesand only removenetworks.$ docker-compose down --volumes --remove-orphansIf you want to preserve data volumes but ensure networks are completely clean:
$ docker-compose down --remove-orphans $ docker network ls -q --filter "label=com.docker.compose.project=<your_project_name>" | xargs -r docker network rmReplace
<your_project_name>with the name of your Docker Compose project (usually the directory name containingdocker-compose.yml). -
Bring the stack up again with a fresh build: The
--buildflag ensures that container images are rebuilt, which is useful if there were changes in your Dockerfiles.$ docker-compose up -d --build
After performing these steps, your Docker Compose services should be able to resolve each other’s hostnames correctly, restoring inter-container communication.
