[EC2 + Docker + Django + Celery + RabbitMQ] EC2 + Docker 환경에서 Celery 세팅 및 테스트

이수진·2022년 8월 6일
2
post-thumbnail

이번에는 EC2와 Docker환경에서 django와 nginx 컨테이너가 띄워져 있는 환경에서
celery도 함께 세팅하고 이를 테스트해보겠습니다.

RabbitMQ, celery_worker, celery_beat 총 3개의 컨테이너를 더 추가해
총 컨테이너는 5개가 됩니다.

✔️프로젝트 아키첵처

✔️설치

$ pip install celery
$ pip install django-celery-results
$ pip install django-celery-beat

✔️ settings.py 파일 설정


# settings.py


# Application definition
INSTALLED_APPS = [
    ...
    
    # celery
    'django_celery_beat',
    'django_celery_results',
]


# Celery
CELERY_BROKER_URL = 'AWS public DNS 주소'
CELERY_RESULT_BACKEND = 'django-db'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'

...

✔️docker-compose 파일 설정

version: '3'
services:

  web:
    container_name: web
    build:
      context: ./
      dockerfile: Dockerfile.prod
    command: gunicorn 프로젝트명.wsgi:application --bind 0.0.0.0:8000
    environment:
      DJANGO_SETTINGS_MODULE: 프로젝트명.settings.prod
    env_file:
      - .env
    volumes:
      - static:/home/app/web/static
      - media:/home/app/web/media
    expose:
      - 8000
    entrypoint:
      - sh
      - config/docker/entrypoint.prod.sh

  nginx:
    container_name: nginx
    build: ./config/nginx
    volumes:
      - static:/home/app/web/static
      - media:/home/app/web/media
    ports:
      - "80:80"
    depends_on:
      - web


  rabbitmq:
    container_name: rabbitmq
    image: rabbitmq:3.7-alpine
    environment:
      - RABBITMQ_USER=guest
      - RABBITMQ_PASSWORD=guest
    ports:
      - "5672:5672" # Default Port
      - "15672:15672" # For UI
    expose:
      - "15672"


  celery_worker:
    container_name: celery_worker
    build:
      context: ./
      dockerfile: Dockerfile.prod
    ports: []
    depends_on:
      - web
      - rabbitmq
    command: sh -c "celery -A 프로젝트명 worker --loglevel=info"

  celery_beat:
    container_name: celery_beat
    build:
      context: ./
      dockerfile: Dockerfile.prod
    ports: []
    depends_on:
        - web
        - rabbitmq
        - celery_worker
    command: sh -c "celery -A 프로젝트명 beat --loglevel=info"


volumes:
  static:
  media:

총 5개의 컨테이너를 띄울 겁니다.
(web, nginx, rabbitmq, celery_worker, celery_beat 총 5개의 컨테이너)

✔️celery.py 와 tasks.py 파일 정의하기

celery.py 는 프로젝트 디렉토리에,
task.py 는 앱 디렉토리 안에 위치해 있어야합니다.


# celery.py

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from celery.schedules import crontab

# 기본 장고파일 설정
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '프로젝트명.settings')
app = Celery('프로젝트명')
app.config_from_object('django.conf:settings', namespace='CELERY')

#등록된 장고 앱 설정에서 task 불러오기
app.autodiscover_tasks()

# task 함수 주기 설정
app.conf.beat_schedule = {
    'api1': {  # 스케쥴링 이름
        'task': 'main.tasks.api1_update',  # 수행할 task 설정
        'schedule': crontab(minute=41, hour='*'),  # 매 시각 41분마다 호출
    },
} 

# tasks.py

from __future__ import absolute_import, unicode_literals
from celery import shared_task

from dnd_7th_4_backend.celery import app


# api1 재호출 시 필요한 함수 -> update
@shared_task
def api1_update():
    func1_update()

✔️ 확인해보기

먼저 이렇게 5개의 컨테이너가 잘 빌드된 것을 확인할 수 있습니다.

그 다음에는 celery_beat 컨테이너의 로그를 찍어보면 다음과 같습니다.

ubuntu@ip-172-31-45-97:~$ docker logs 33
[2022-08-13 09:30:03,620: INFO/MainProcess] beat: Starting...
[2022-08-13 09:41:00,059: INFO/MainProcess] Scheduler: Sending due task api1 (main.tasks.api1_update)
[2022-08-13 10:41:00,049: INFO/MainProcess] Scheduler: Sending due task api1 (main.tasks.api1_update)
[2022-08-13 11:41:00,041: INFO/MainProcess] Scheduler: Sending due task api1 (main.tasks.api1_update)

보면 스케줄러가 등록해놓은 task를 등록한 시간마다 보내고 있는 것을 확인할 수 있습니다.

celery_worker의 컨테이너를 확인해볼까요?
celery_worker 컨테이너의 로그를 찍어보면 다음과 같습니다.

.
.
.
[2022-08-13 11:43:41,744: INFO/ForkPoolWorker-1] Task main.tasks.api1_update[850e0f56-ed8d-482d-a6ef-52e9dc67140f] succeeded in 161.69972267199773s: None

결과 출력창 맨 마지막만 확인해보면 다음과 같습니다.
task를 수행했고, 성공했으며 결린 시간이 함께 나와있습니다.

제가 등록한 task를 통해서
데이터베이스의 결과가 업데이트 되었음을 직접 확인할 수 있었습니다🙆🏻‍♀️

profile
꾸준히, 열심히, 그리고 잘하자

0개의 댓글