DEV Community

Nico Reyes
Nico Reyes

Posted on

Docker said 'Connection refused'. Localhost worked fine. The problem was one line.

Last week I containerized an app that was running fine locally. Deployed to Docker. Got connection refused errors immediately.

Checked the port mapping. Correct. Checked the environment variables. Correct. Restarted the container probably 15 times.

Logged into the container to debug. Ran curl localhost:3000 from inside. Worked perfectly.

Ran the same curl from my host machine.

Connection refused.

The actual problem

The app was binding to 127.0.0.1:3000.

Docker containers need to bind to 0.0.0.0 to accept connections from outside the container. Localhost only accepts connections from inside the container itself.

Changed this:

const express = require('express');
const app = express();

// This only works inside the container
app.listen(3000, '127.0.0.1', () => {
  console.log('Server running on port 3000');
});
Enter fullscreen mode Exit fullscreen mode

To this:

const express = require('express');
const app = express();

// This accepts external connections
app.listen(3000, '0.0.0.0', () => {
  console.log('Server running on port 3000');
});
Enter fullscreen mode Exit fullscreen mode

Rebuilt the image.

Worked immediately.

127.0.0.1 means "this machine only". Inside a container, "this machine" is the container itself, not your host.

0.0.0.0 means "all network interfaces". Lets Docker's port mapping actually route traffic to your app.

Most frameworks default to 0.0.0.0 when you don't specify. Express doesn't if you pass a host parameter. Fun.

Before I figured that out

Rebuilt the image 4 times thinking cache was stale.

Changed port numbers. Tried 3000, 8000, 5000.

Added EXPOSE 3000 to Dockerfile. That doesn't actually do anything for networking btw.

Googled "docker connection refused" and got 50 different answers.

Checked firewall rules. Wasn't that.

Wasted about 2 hours. The error message gives zero hints about bind addresses.

Top comments (0)