Search code examples
dockerdocker-composerabbitmqcelerycelerybeat

Why can't celery worker connect to rabbitmq using docker compose


I am trying to combine my services using docker compose but my celery and celery beat services can't connect with my rabbitmq service. Here is my rabbitmq service in the docker-compose.yml file

rabbitmq:
    container_name: "rabbitmq"
    image: rabbitmq:3-management
    ports:
      - 15672:15672
      - 5672:5672
    environment:
      - RABBITMQ_DEFAULT_USER=guest
      - RABBITMQ_DEFAULT_PASS=guest
    depends_on:
      - server
    volumes:
      - rabbitmq:/var/lib/rabbitmq

and here are my celery worker and celery beat services in docker-compose.yml

celery_worker:
    container_name: celery-worker
    build: .
    command: celery -A tasks worker -E --loglevel=INFO
    environment:
      host_server: postgresqldb
      db_server_port: 5432
      database_name: db
      db_username: user
      db_password: password
      ssl_mode: prefer
    networks:
      - postgresqlnet
    depends_on:
      - rabbitmq

  celery_beat:
    container_name: celery-beat
    build: .
    command: celery -A tasks beat
    environment:
      - host_server=postgresqldb
      - db_server_port=5432
      - database_name=db
      - db_username=user
      - db_password=password
      - ssl_mode=prefer
    networks:
      - postgresqlnet
    depends_on:
      - rabbitmq

I also have a celeryconfig.py where broker url is stored. It's content are below

broker_url = "amqp://guest:guest@localhost:5672//"

When I run docker compose up I get this output from celery and celery beat.

celery-worker     | [2023-02-03 14:24:43,223: ERROR/MainProcess] consumer: Cannot connect to amqp://guest:**@127.0.0.1:5672//: [Errno 111] Connection refused.
celery-worker     | Trying again in 32.00 seconds... (16/100)
celery-worker     | 
celery-beat       | [2023-02-03 14:25:10,058: ERROR/MainProcess] beat: Connection error: [Errno 111] Connection refused. Trying again in 32.0 seconds...

Solution

  • I encountered a similar issue where my Celery worker could not connect to the RabbitMQ service when orchestrated with Docker Compose. The solution that worked for me involved changing the network mode to host the involved services. This allows the services to communicate over the host's network, eliminating the need for port mappings and making service discovery straightforward since they can connect via localhost.

    Here's how you can adjust your Docker Compose configuration:

    For your RabbitMQ service:

    rabbitmq:
      container_name: "rabbitmq"
      image: rabbitmq:3-management
      environment:
        - RABBITMQ_DEFAULT_USER=guest
        - RABBITMQ_DEFAULT_PASS=guest
      volumes:
        - rabbitmq:/var/lib/rabbitmq
      network_mode: "host"
    

    And for your Celery worker and Celery beat services:

    celery_worker:
       #
       network_mode: "host"
    
    celery_beat:
       # 
       network_mode: "host"
    

    Make sure to adjust the broker_url in your celeryconfig.py to point to localhost or the host's IP address since all services are now on the host network:

    broker_url = "amqp://guest:guest@localhost:5672//"
    

    This configuration allows your Celery worker and beat services to successfully connect to RabbitMQ using localhost, as they're all utilizing the host's networking. Do note that using network_mode: "host" makes your services use the host's network stack directly, and this approach is typically more suited for Linux environments. It might behave differently on Docker for Windows or Mac, due to differences in how networking is implemented.