DEV Community

Nico Reyes
Nico Reyes

Posted on

Docker said 'healthy'. My app said 'connection refused'. 4 hours gone.

Docker said 'healthy'. My app said 'connection refused'. 4 hours gone.

Last week I deployed something that should've been straightforward. Docker Compose, two containers, one talks to the other. Classic setup. Everything looked fine in docker ps. Both containers "healthy". Except my API couldn't reach the database and had no idea why.

What I saw

docker ps showed both containers up. Postgres on port 5432, my API on 3000. STATUS said "healthy" for both.

My app starts up, tries to connect to postgres:5432, and immediately throws "connection refused".

Tried localhost:5432. Tried 127.0.0.1:5432. Tried the container IP I found via docker inspect. Nothing worked.

What I did wrong first

Restarted everything. Updated docker-compose. Pulled fresh images. Wrote a test script to verify the port was open. That script worked fine when run locally but my actual app still couldn't connect.

At this point I'm googling "docker connection refused postgres" and trying every solution. Most of them assume you haven't already verified the port is accessible.

Then I noticed something in docker network inspect. My containers were on different networks.

The actual problem

My docker-compose had something like:

services:
  api:
    build: ./api
    ports:
      - "3000:3000"
    networks:
      - frontend
  postgres:
    image: postgres:15
    ports:
      - "5432:5432"
    networks:
      - backend
Enter fullscreen mode Exit fullscreen mode

Api on frontend network. Postgres on backend network. They couldn't talk to each other even though both were running on the same Docker host.

The health check passed because it was just checking if postgres process was alive, not whether other containers could reach it.

The fix

services:
  api:
    build: ./api
    ports:
      - "3000:3000"
    networks:
      - frontend
      - backend
    depends_on:
      - postgres
  postgres:
    image: postgres:15
    ports:
      - "5432:5432"
    networks:
      - backend

networks:
  frontend:
  backend:
Enter fullscreen mode Exit fullscreen mode

Put both on the same network. Restarted. Worked immediately.

The kicker

Docker Compose doesn't automatically put all containers on the same network. Each service only gets a network if you explicitly assign it. If you add a service without specifying networks, you get whatever the default is. And if you have multiple services with no explicit assignment, they might not share a network depending on how your Compose file is structured.

Health checks lie sometimes too. A container can be "healthy" while the actual application inside it can't do its job. The health check is scoped to what you tell it to check, not real world connectivity.

"Connection refused" is technically accurate but not that helpful when you're debugging across multiple layers. Wrong port, wrong host, network isolation. All give you the same error.

Been explicit with networks ever since. Every service gets assigned, nothing is left to defaults. Learned this one the hard way.

Top comments (0)