Debugging “curl (56) Recv failure: Connection reset by peer” When Accessing Docker Container from Host


1 views

You're experiencing a classic Docker networking issue where:

  • The service works inside the container (docker exec curl succeeds)
  • Host-to-container communication fails with connection reset
  • The container ports are correctly mapped (0.0.0.0:80->80/tcp)

First, verify the container's listening ports:

docker exec b56fa0d76d5c netstat -tulnp | grep 80

Check if the service binds to localhost only:

docker exec b56fa0d76d5c ss -tulnp | grep 80
# If output shows "127.0.0.1:80", that's the problem

The web service inside your container might be configured to:

  1. Bind only to 127.0.0.1 (localhost)
  2. Reject connections from outside the container
  3. Have firewall rules blocking the traffic

1. Modify Service Binding

For Node.js applications, change the listen address:

app.listen(80, '0.0.0.0', () => {
  console.log('Server listening on all interfaces');
});

For Python Flask:

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)

2. Docker Network Inspection

Check your container's network configuration:

docker inspect b56fa0d76d5c | jq '.[].NetworkSettings'

3. Testing with Alternative Tools

Try telnet to verify basic connectivity:

telnet localhost 80
# Or for more detailed debugging:
nc -zv localhost 80

Use tcpdump inside the container:

docker exec -it b56fa0d76d5c bash -c "apt-get update && apt-get install tcpdump -y"
docker exec b56fa0d76d5c tcpdump -i any port 80 -vv

Check container logs for errors:

docker logs --tail 50 b56fa0d76d5c

When binding to 0.0.0.0:

  • Ensure proper firewall rules are in place
  • Consider using Docker's built-in firewall (--iptables flag)
  • Implement authentication for sensitive endpoints

When working with Docker containers on AWS EC2 instances, a common but frustrating scenario occurs when a service is accessible from within the container but refuses connections from the host. Let's examine this networking puzzle through a real-world example.

# Container is running with ports exposed
docker ps
CONTAINER ID   IMAGE                        PORTS                                   NAMES
b56fa0d76d5c   registry/work/metrics:v0.1.0 0.0.0.0:80->80/tcp, 0.0.0.0:9000->9000/tcp  insane_leakey

First, confirm the service works inside the container:

docker exec -it b56fa0d76d5c bash
root@b56fa0d76d5c:/# curl 'http://localhost/health'
Request is missing required query parameter 'apiName'

But fails from host:

curl 'http://localhost/health'
curl: (56) Recv failure: Connection reset by peer

The connection reset typically indicates one of these issues:

# 1. Check container binding
docker inspect b56fa0d76d5c | grep HostPort

# 2. Verify firewall rules
sudo iptables -L -n | grep 80

# 3. Test alternative ports
curl -v 'http://localhost:9000/health'

# 4. Validate service binding
docker exec b56fa0d76d5c netstat -tulnp | grep 80

Docker's default bridge networking can sometimes cause routing issues. Try these alternatives:

# Option 1: Use host networking
docker run --network=host ...

# Option 2: Explicit port binding
docker run -p 127.0.0.1:80:80 ...

On AWS environments, additional checks are needed:

# Check security group inbound rules
aws ec2 describe-security-groups --group-ids sg-xxxxxx

# Verify instance metadata service
curl http://169.254.169.254/latest/meta-data/...
  1. Confirm container port exposure with docker port <container>
  2. Test with different IP bindings (127.0.0.1 vs 0.0.0.0)
  3. Verify SELinux/AppArmor policies aren't blocking connections
  4. Check Docker daemon logs for networking errors
  5. Test with simplified container images (nginx) to isolate the issue