일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- OS
- none이미지
- java.util.function
- ReflectUtils
- Thread Library
- Spring
- django-crontab
- spring-data-jpa
- 문자열 리터럴
- sql-mappler
- 운영체제
- 쓰레드 라이브러리
- @Header
- rainbow table
- FunctionalInterface
- strict stubbing
- task_struct
- hiberbate
- custom annotation
- Process
- 도커
- 롬복주의점
- python-socketio
- 함수형 인터페이스
- AOP
- functional interface
- 프로세스
- 문자열 불변성
- SystemCall
- Thread Multiplexing
- Today
- Total
JH's Develog
[Django] Docker환경에서 Django-crontab을 활용하여 주기적으로 작업 실행하기 본문
Django를 활용해서 웹서버를 구성할 때 기간만료 처리, 주기적인 이메일 발송 등 특정 작업을 주기적으로 실행하는 상황이 생깁니다. 이때 Django 웹서버에서 리눅스의 Crontab을 기반으로한 django-crontab 라이브러리를 사용하면 주기적인 작업 실행을 쉽게 처리할 수 있습니다.
간단히 django-crontab 작업을 생성해보고 이를 Docker 컨테이너에서 실행시키는 방법을 알아보겠습니다.
django-crontab 설정
pip install django-crontab
pip 으로 간단하게 django-crontab을 설치한 후
setting.py를 수정해줍니다.
INSTALLED_APPS = [
...
'django_crontab'
]
CRONJOBS = [
('* * * * *', 'myapp.cron.my_scheduled_job', '>> ./cron.log'),
]
CRONJOBS의 각 Argument의 의미는 다음과 같습니다.
- ' * * * * * '
* * * * * 수행할 명령어
┬ ┬ ┬ ┬ ┬
│ │ │ │ │
│ │ │ │ │
│ │ │ │ └───────── 요일 (0 - 6) (0:일요일, 1:월요일, 2:화요일, …, 6:토요일)
│ │ │ └───────── 월 (1 - 12)
│ │ └───────── 일 (1 - 31)
│ └───────── 시 (0 - 23)
└───────── 분 (0 - 59)
작업이 실행될 주기를 설정합니다. 위 설정은 매분마다 작업을 실행한다는 의미이며 앞부터 분/시/일/월/요일 을 나타냅니다. 시간 설정을 도와주는 유용한 사이트가 있으니 참고 바랍니다.
- 'myapp.cron.my_scheduled_job'
실행할 작업을 정의합니다. 저는 cron.py 파일안에 my_scheduled_job라는 함수를 정의 해놓았으며, myapp은 cron.py 파일이 들어있는 앱의 이름입니다.
로그 파일에 hello를 출력하는 간단한 job을 구현하면 아래와 같습니다.
#cron.py
def my_scheduled_job():
print('hello')
- '>> ./cron.log'
django-crontab은 내부적으로 리눅스의 crontab을 사용하므로 print를 통해 출력된 내용은 로그 파일에 저장됩니다.
위 설정은 출력 내용을 저장할 로그 파일의 위치를 결정합니다.
여러가지 자세한 설정은 아래 문서를 참고바랍니다.
https://pypi.org/project/django-crontab/
설정완료 후 아래 명령어를 통해 작업을 스케줄러에 등록하고 잘 등록되었는 지 확인할 수 있습니다.
python manage.py crontab add #crontab 작업 등록
python manage.py crontab show #작업 등록 확인
django-crontab을 도커 환경에서 구동하기
먼저 django-crontab은 리눅스 crontab을 활용하는 별도의 시스템 데몬으로 저희가 구현한 Django 웹서버와는 별도의 프로세스를 가지고 작동하는 서비스라고 할 수 있습니다.
Docker Docs의 Run multiple services in a container 문서를 확인해보면
"It is generally recommended that you separate areas of concern by using one service per container"
라는 내용이 존재합니다.
https://docs.docker.com/config/containers/multi-service_container/
즉 하나의 컨테이너에서 여러 개의 서비스를 구동할 수는 있지만, 일반적으로는 하나의 서비스에 하나의 컨테이너를 사용하는 것을 추천한다고 명시되어 있습니다.
그러므로 웹서버와 django-crontab을 별도의 컨테이너에서 실행시키도록 하겠습니다.
먼저 이미지 생성을 위한 Dockerfile을 작성하겠습니다.
#Dockerfile
FROM python:3.7.3
WORKDIR /usr/src/app
COPY . /usr/src/app
WORKDIR .
#pip업그레이드 이후 의존성 설치
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
# for django-crontab
RUN chmod -R 777 /usr/src/app #권한 설정
RUN apt-get update
RUN apt-get install -y cron && touch ./cron.log #crontab 설치 및 로그파일 생성
다음은 Django 웹서버와 django-crontab을 별도의 컨테이너에서 실행시키기 위한 docker-compose.yml파일 설정입니다.
version: "3"
services:
_build_image:
image: main_image
build: .
my_django:
image: main_image
restart: always
command: python manage.py runserver 0.0.0.0:8000
ports:
- 8000:8000
env_file:
- ./.env
depends_on:
- _build_image
cron:
image: main_image
restart: always
command: bash -c "service cron start && python manage.py crontab add && tail -f /dev/null"
env_file:
- ./.env
depends_on:
- my_django
- django-crontab과 Django웹서버는 서로 다른 프로세스이지만 같은 코드를 사용하기 때문에 _build_image에서 현재 폴더를 한번만 빌드해서 main_image를 만든 후 각 서비스에서 main_image를 사용하도록 설정하였습니다.
이렇게 하면 도커 실행 시에 이미지를 두번 빌드할 필요 없이 한번만 빌드해도 컨테이너를 실행할 수 있습니다.
- main_image가 생성된 후에 my_django과 cron 서비스가 실행되어야 하므로 depends_on을 통해 의존성을 결정해 줍니다.
- cron 서비스의 command에서 "service cron start && python manage.py crontab add" 만 실행한다면 스케줄러에 crontab 작업을 등록하는 python manage.py crontab add 작업이 끝났을때 컨테이너가 exited 되어버리기 때문에
"tail -f /dev/null"을 추가해서 컨테이너가 종료되지 않도록 설정합니다.
이후 docker-compose up을 통해 도커를 실행하면 Django웹서버가 정상적으로 동작하고 django-crontab 서비스도 스케쥴러에 정상적으로 등록된 것을 확인할 수 있습니다.
'Django' 카테고리의 다른 글
[Django] python-socketio로 Socket.io 서버 구성하기 (0) | 2021.12.27 |
---|