Skip to content
Community

EXPLORE TOPICS

Editorial approach

New to CoreTrailKit?

Observe your services. Keep the evidence close.

CoreTrailKit
Back to articles
GUIDE/ Docker

Docker Compose: fix localhost connection refused

Your database accepts connections from a desktop client, but the API container reports ECONNREFUSED. Before changing passwords or publishing more ports, identify where the connection originates. A working host connection does not establish a working container-to-container path.

By CoreTrailKit4 min read

01

Read the destination before changing the server

Record the failing host and port from the application configuration, along with the service that emitted the error. In the common failure, the API tries localhost:15432 because that is the address used by a database client on the host. Inside the API container, localhost refers to that container, not to the database service.

Treat error classes separately. Connection refused means a TCP connection was rejected at that destination; it is not proof of a bad database password. Name-resolution failures, timeouts, authentication failures, and protocol errors require different next checks. Preserve the original error before editing configuration.

02

Compare the two address spaces

Compose services on a shared network can discover each other by service name. With a database service named db listening internally on 5432 and published as 15432:5432, an API on that network normally uses db:5432. A host-side client uses the published host address and port instead.

Write both paths down. For example: host client → localhost:15432 → db:5432; API container → db:5432. If those paths are mixed, changing the host mapping cannot repair the API’s destination. Avoid depending on a container IP, because recreating the service can change it.

bash · EXAMPLE
# Host-side inspection; does not change the stack.
 docker compose ps
 docker compose port db 5432
 docker compose logs --tail=80 api db
 # Inspect configured networks without dumping container environment variables.
 docker inspect --format '{{json .NetworkSettings.Networks}}' "$(docker compose ps -q api)"
 docker inspect --format '{{json .NetworkSettings.Networks}}' "$(docker compose ps -q db)"

03

Use the service name and internal port

The excerpt below publishes a database port only for host tools. The API uses a different host and port because it is a peer on the Compose network. Environment variable names must match what your application actually reads; DB_HOST is an example, not a Compose feature.

When services belong to different Compose projects, verify that they deliberately share a network. A matching service name alone does not join networks. Keep database exposure limited to the interfaces that need it; adding a public port is not a substitute for correct network membership.

yaml · EXAMPLE
services:
  api:
    build: ./api
    environment:
      DB_HOST: db
      DB_PORT: "5432"
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:?set a local test password}"
    ports:
      - "127.0.0.1:15432:5432"

04

Check the listener and startup timing independently

If name and port are correct, inspect the database listener and network membership. A service bound only to its own loopback interface will not accept connections from a peer container. Prefer the database’s own diagnostics over assuming every image contains curl, ping, or a shell.

A service can also be started without being ready to accept work. Compose dependency ordering and a health-based dependency condition can help with initial startup, but the application still needs bounded retries and reconnection behavior for later outages. Do not confuse a timing fix with an address fix.

05

Verify from the same place that failed

Restart or recreate only the service whose connection configuration changed, using your normal deployment process. Make the API perform a real database operation and compare its new error or success with the original. A host-side database client passing again is not the decisive test.

Recheck after a controlled restart of the dependency in a disposable environment. The useful outcome is that the API reaches the intended database, authenticates, and recovers as designed. A container marked running, by itself, confirms none of those application-level properties.

Know the limits

This guide covers ordinary bridge-network Compose services. Host networking, external databases, proxies, and platform-specific host access require their own address model. The YAML is an illustrative fragment, not a production database deployment.

Sources & further reading

A technical publication by CoreTrailKit.

Browse all articles

CONTINUE EXPLORING