我有一个 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))
设置.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:
为 passed to it as arguments但您的脚本会忽略这些。
解决此问题的最佳方法是传递特定命令 - “运行 Django 服务器”、“运行 Celery Worker” - 作为 Dockerfile CMD
或 Compose 命令:
.入口点脚本以 shell 命令 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 "$@"
行时,它将运行提供的命令。
这意味着您可以从 app
容器中删除 command:
覆盖。 (您确实需要将其保留给 Celery 容器。)您可以通过删除 image:
和 container_name:
设置来进一步简化此设置(Compose 将为这两个设置选择合理的默认值)其中)和隐藏图像内容的 volumes:
安装。
关于python - Celery 任务未在 docker-compose 中运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72587417/