19

I've done a lot of searching but I cannot fix this issue.

I have a basic Rabbitmq container running via this command:

docker run -d --hostname rabbitmqhost --name rabbitmq -p 15672:15672 -p 5672:5672 rabbitmq:3-management

I am using nameko to create a microservice which connects to this container. Here's a basic microservice module main.py:

from nameko.rpc import rpc
class Service_Name(object):
    name = "service_name"

    @rpc
    def service_endpoint(self, arg=None):
        logging.info('service_one endpoint, arg = %s', arg)

This service runs and connects to the rabbitmq from my host machine with the command:

nameko run main --broker amqp://guest:guest@localhost

I wanted to put the service into a Docker container (called service_one) but when I do so and run the previous nameko command I get socket.error: [Errno 111] ECONNREFUSED no matter how I try and link the two containers.

What would be the correct method? The aim is to have each service in a container, all talking to each other through rabbit. Thanks.

steve
  • 537
  • 1
  • 7
  • 17
  • "No matter how I try to link the two containers..." What have you tried? – larsks Nov 12 '16 at 14:12
  • I tried link and network, turns out I was getting the ampq connection values slightly wrong for each method. (I was using localhost rather than AMQ_PORT_5672_TCP_ADDR etc). – steve Nov 12 '16 at 14:53

1 Answers1

31

If you're running a service inside a container, then amqp://guest:guest@localhost won't do you any good; localhost refers to the network namespace of the container...so of course you get an ECONNREFUSED, because there's nothing listening there.

If you want to connect to a service in another container, you need to use the ip address of that container, or a hostname that resolves to the ip address of that container.

If you are running your containers in a user-defined network, then Docker maintains a DNS server that will map container names to addresses. That is, if I first create a network:

docker network create myapp_net

And then start a rabbitmq container in that network:

docker run -d --network myapp_net --hostname rabbitmqhost \
   --name rabbitmq -p 15672:15672 -p 5672:5672 rabbitmq:3-management

Then other containers started in that network will be able to use the hostname rabbitmq to connect to that container.

For containers running in the default network (no --network parameter on the command line), you can use the --link option to achieve a similar, though less flexible, effect, as documented here.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • Thank you. I ended up using --link to connect each service container to rabbit, even though I appreciate the above is the new standard way of doing it. – steve Nov 12 '16 at 14:52
  • 1
    I just wanted to highlight one advantage of the Docker network solution: when using `--link`, if you stop your rabbitmq container, your app is out of luck: you can't "relink" the container after starting a new rabbitmq container. On the other hand, using Docker networks, which rely on dns for name resolution, if you start a new container with the same name as the new container, your services will probably be able to recover (presuming that your application code handles disconnections gracefully). – larsks Nov 12 '16 at 15:39
  • Ahh, that's a very good point, thank you. If I were to use the network solution, what would be the address and port of rabbit? i.e. The equivalent of `AMQ_PORT_5672_TCP_ADDR` and `AMQ_PORT_5672_TCP_PORT` – steve Nov 12 '16 at 17:07
  • 1
    The address would just be the name (`--name ...`) of the container (Docker maintains a DNS server that maps container names to address). There is no equivalent to `AMQ_PORT_5672_TCP_PORT`, but in general this isn't an issue. – larsks Nov 13 '16 at 00:22
  • Great, thanks again. The only issue I now have is that I cannot access my Flask app (on 0.0.0.0:5000) anymore when the app's container is connected to that network, any ideas? – steve Nov 13 '16 at 11:33
  • Turns out I just didn't map the ports correctly, one I ran with -p 5000:5000 it all works. – steve Nov 13 '16 at 11:43
  • One important point to make here is that all of your service containers need to be started using `--name`. As I found out, without it, container is created but is not put inside the network even if you specify `--network`, thus failing to connect to rabbitMQ – O.MeeKoh May 13 '22 at 18:27