E. Jaep
E. Jaep

Reputation: 2153

Failing to connect to localhost from inside a container Connection refused

I'm currently testing an Ansible role using Molecule. Basically, Molecule launches a container that is Ansible compliant and runs the role on it.

In order to test the container, Molecule also embed unit tests using Testinfra. The python unit tests are run from within the container so you can check the compliance of the role.

As I'm working on an Nginx based role, one of the unit tests is simply issuing a curl http://localhost:80

I do get the below error message in response:

curl: (7) Failed to connect to localhost port 80: Connection refused

When I:

nginx answers correctly.

Therefore, I believe that:

My questions are the following:

  1. Am I correct?
  2. Can this difference be overcome so the curl would work?

Upvotes: 0

Views: 5001

Answers (2)

E. Jaep
E. Jaep

Reputation: 2153

it actually have nothing to do with the differences between Docker and Vagrant (i.e. containers vs VMs).

The testInfra code is actually run from outside the container / VM, hence the fact the subprocess.call(['curl', 'http://localhost']) is failing.

In order to run a command from the container / VM, I should use:

host.check_output('curl http://localhost')

Upvotes: 0

BMitch
BMitch

Reputation: 263636

Docker containers start in their own network namespace by default. This namespace includes a separate loopback interface (127.0.0.1) that is distinct from the same interface on the host and any other containers. If you want to access an application from another container or via a published port on the host, you need to listen on all interfaces (0.0.0.0) rather than the loopback interface.

One other issue I often see is at some layer in the connection (the host, or inside of a container), the "localhost" name is mapped to the IPv6 value of ::1 in the /etc/host file, and somewhere in that connection only the IPv4 value is valid (either where the port was published, the application is listening, or IPv6 isn't enabled on the host or docker engine). Therefore, make sure to try connecting to the IPv4 address directly, 127.0.0.1, to eliminate any potential IPv6 issues.

Regarding the curl command and how to correct it, I cannot answer that without more details on how you are running the curl (is it in a separate container), how you are running your application, and how the two are joined on the network (did you create a new network in docker for your application and unit tests to run). The typical solution is to create a new network in docker, run both containers on that network, and connect via docker's included DNS to the container or service name of the destination, e.g. curl http://my_app/.


Edit: based on the comments, if your application and curl command are both running inside the same container, then curl http://127.0.0.1/ should work. There's no change I'm aware of needed with to curl to make it work inside of a container vs on a VM. The error you are seeing is likely from the application not starting and listening on the port as expected, possibly a race condition where the curl command is run too soon, or the base assumptions of how the tool works is incorrect. Start by changing the unit test to verify the application is up and running and listening on the port with commands like ps -ef and ss -lt.

Upvotes: 1

Related Questions