Задачи Celery не выполняются в docker-compose

У меня есть docker-compose, в котором есть три компонента: app, celery и redis. Они реализованы в DjangoRest.

Я видел этот вопрос несколько раз на stackoverflow и попробовал все перечисленные решения. Однако задача celery не запускается.

Поведение, которое имеет celery, такое же, как и у приложения, то есть он запускает проект django, но не запускает задачу.

docker-compose.yml

version: "3.8"
services:
  app:
    build: .
    volumes:
      - .:/django
    ports:
      - 8000:8000
    image: app:django
    container_name: myapp
    command: python manage.py runserver 0.0.0.0:8000
    depends_on:
      - redis
  redis:
    image: redis:alpine
    container_name: redis
    ports:
      - 6379:6379
    volumes:
      - ./redis/data:/data
    restart: always
    environment:
      - REDIS_PASSWORD=
    healthcheck:
      test: redis-cli ping
      interval: 1s
      timeout: 3s
      retries: 30

  celery:
    image: celery:3.1
    container_name: celery
    restart: unless-stopped
    build:
      context: .
      dockerfile: Dockerfile
    command: celery -A myapp worker -l INFO -c 8
    volumes:
      - .:/django
    depends_on:
      - redis
      - app
    links:
      - redis

DockerFile

FROM python:3.9

RUN useradd --create-home --shell /bin/bash django
USER django

ENV DockerHOME=/home/django

RUN mkdir -p $DockerHOME
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV PIP_DISABLE_PIP_VERSION_CHECK 1

USER root
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
RUN apt-get -y update
RUN apt-get install -y google-chrome-stable

USER django
WORKDIR /home/django
COPY requirements.txt ./

# set path
ENV PATH=/home/django/.local/bin:$PATH

# Upgrade pip and install requirements.txt
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
COPY . .

EXPOSE 8000

# entrypoint
ENTRYPOINT ["/bin/bash", "-e", "docker-entrypoint.sh"]

docker-entrypoint.sh

# run migration first
python manage.py migrate

# create test dev user and test superuser
echo 'import create_test_users' | python manage.py shell

# start the server
python manage.py runserver 0.0.0.0:8000

celery.py

from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')
app = Celery('myapp', broker='redis://redis:6379')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

settings.py

CELERY_BROKER_URL     = os.getenv('REDIS_URL') # "redis://redis:6379"
CELERY_RESULT_BACKEND = os.getenv('REDIS_URL') # ""redis://redis:6379"
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Africa/Nairobi'

Ваш docker-entrypoint.sh скрипт безоговорочно запускает сервер Django. Поскольку вы объявляете его как ENTRYPOINT изображение, Compose command: передается ему в качестве аргументов , но ваш скрипт игнорирует их.

Лучший способ исправить это - передать конкретную команду - "запустить сервер Django", "запустить Celery worker" - как Dockerfile CMD или Compose command:. Сценарий точки входа заканчивается командой оболочки exec "$@" для выполнения этой команды.

#!/bin/sh
python manage.py migrate
echo 'import create_test_users' | python manage.py shell

# run the container CMD
exec "$@"

В вашем Dockerfile необходимо объявить значение по умолчанию CMD.

ENTRYPOINT ["./docker-entrypoint.sh"]
CMD python manage.py runserver 0.0.0.0:8000

Теперь в настройках Compose, если вы не укажете command:, будет использована команда по умолчанию CMD, а если укажете, то она будет запущена вместо нее. В обоих случаях будет запущен ваш сценарий точки входа, но когда он дойдет до последней строки exec "$@", он выполнит предоставленную команду.

Это означает, что вы можете удалить переопределение command: из вашего контейнера app. (Вы должны оставить его для контейнера Celery.) Вы можете упростить эту настройку, удалив параметры image: и container_name: (Compose выберет разумные значения по умолчанию для обоих) и крепление volumes:, которое скрывает содержимое изображения.

Вернуться на верх