After lots and lots of searches. Here is the solution I have found:
requirements.txt
file so they can be installed by docker when the container is created:Django>=4.0
psycopg2>=2.9
factory_boy==3.2.1
django-crontab==0.7.1
django_crontab
to your project’s INSTALLED_APPS
. IMPORTANT to note that its django_crontab
not django-crontab
INSTALLED_APPS = [
'django_crontab',
...
]
watchman/cron.py
from watchman.factories import RecordFactory
def change_timezones():
record = RecordFactory()
record.save()
CRONJOBS
in the settings.py
fileCRONJOBS = [
('* * * * *', 'watchman.cron.change_timezones')
]
Dockerfile
is pretty standard, but we can install cron
and vim
packages. vim
isn’t required but it does make it easier to debug stuff.# syntax=docker/dockerfile:1
FROM python:3
RUN apt-get update && apt-get install -y cron vim # Installing cron and vim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code
docker-compose.yml
file, we need to add another container which will run the cron job. Since docker containers run one process, so we can’t run this inside the container for the frontend. In the cron
container, we will add all our cron jobs with python [manage.py](http://manage.py) crontab add
and then run cron -f
which runs cron as a foreground process. We need to provide our environment variables here so we our cron job can access the database. So here’s our updated docker-compose.yml
file:version: "3.9"
services:
db:
...
web:
...
cron:
build: .
command: bash -c "python manage.py crontab add && cron -f"
depends_on:
- db
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
crontab
still won’t be able to access these variables because of some weird reason? An easy way to fix this is to manually specify the environment variables along with the command. To do this, we can specify a CRONJOB_COMMAND_PREFIX
in the settings.py
file as follows:CRONTAB_COMMAND_PREFIX = f"POSTGRES_DB={os.environ.get('POSTGRES_DB')} POSTGRES_USER={os.environ.get('POSTGRES_USER')} POSTGRES_PASSWORD={os.environ.get('POSTGRES_PASSWORD')}"
cron
container and running crontab -l
which will give you the following outputcrontab -l
# Expected Output:
* * * * * POSTGRES_DB=postgres POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres /usr/local/bin/python /code/manage.py crontab run a7953f0b20e26eb1fc404bb5bd57d0d4 # django-cronjobs for core