Django channels between different docker containers

I'm working with django channels and I have a problem about how to deal with sending a message using channels

Context

I have 2 containers: celery-worker and api, I want to send data via websockets from celery-worker container to the browser through api container using channels, here a picture:

enter image description here

Question

Do you know how to "initialize" channels in api container and use this channels inside celery-worker container? to after in celery-worker container call only to Group('pablo').send(message) and it automatically send to the browser.

Any advice will be ok.

Note: I tried to not post code because is very extensive and maybe It would result difficult to understand the question but if you want I can post some code that you need.

Upvotes: 6

Views: 1446

Answers (2)

pplonski
pplonski

Reputation: 5839

I have created the example (with simple tasks) that is using Celery and Django Channels 2 (github). Celery worker is sending to channel layer messages. Messages are broadcasted to clients that are connected to websocket.

On server side I have consumer:

class TasksConsumer(AsyncWebsocketConsumer):

    async def connect(self):
        # One group name for all clients: 'tasks'
        self.group_name = 'tasks'
        await self.channel_layer.group_add(self.group_name, self.channel_name)
        await self.accept()

    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(self.group_name, self.channel_name)

    async def receive(self, text_data):
        pass

    async def task_update_message(self, event):
        # Send message to channel
        await self.send(json.dumps(event))

You can see that the group name is 'tasks'. On celery side, worker is calling:

channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)("tasks", msg)

To use channels in worker code, you need to set django settings:

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings')
import django
django.setup()

Hope it helps!

Upvotes: 1

Eddwin Paz
Eddwin Paz

Reputation: 2868

You need to let know other containers that you depend on them. Example. Here you see that PostgreSQL has dependencies from user_service and notification_service you need to add this for each container that wants to use other containers either linked or dependant. here is an example.

version: '3'
services:
db:
    image: postgres
    ports:
    - '5434:5434'
user_service:
    build: ""
    environment:
    - JWT_SECRET=mysecret_json_web_token_pass
    command: python user/app.py
    volumes:
    - .:/microservices
    ports:
    - "9001:9001"
    depends_on:
    - db
notification_service:
    build: ""
    environment:
    - JWT_SECRET=mysecret_json_web_token_pass
    command: python notification/app.py
    volumes:
    - .:/microservices
    ports:
    - "9002:9002"
    depends_on:
    - db

for your case you might want to add depends_on: - celery - redis

You can also stablish a local network.. but Rather than doing that I created containers in the same docker-compose that way they know eachother.

Here is another example

version: '2'  
services:  
nginx:
    image: nginx:latest
    container_name: nx01
    ports:
    - "8001:8001"
    volumes:
    - ../src:/src
    - ./static:/static
    - ./media:/media/
    - ./config/nginx:/etc/nginx/conf.d
    depends_on:
    - web
web:
    build: .
    container_name: dg01
    command: gunicorn mydjango.wsgi 0.0.0.0:8000

    depends_on:
    - db
    links:
    - redis
    volumes:
    - ../src:/src
    - ./static:/static
    - ./media:/media/
    expose:
    - "8001"
db:
    image: postgres:latest
    container_name: pq01
    ports:
    - "5432:5432"

redis:
    image: redis:latest
    container_name: rd01
    ports:
    - '6379:6379'

celery:
    build: .
    container_name: cl01
    command: celery worker --app=app.tasks
    volumes:
    - ..:/src
    links:
    - db
    - redis

to call it on your code... use it like this.

CELERY_BROKER_URL = 'redis://redis:6379/0'
CELERY_RESULT_BACKEND = 'redis://redis:6379/0'

Upvotes: 0

Related Questions