我正在尝试在docker容器中运行芹菜,并且由于某种原因它永远不会更新。每当我在tasks.py
中添加新函数或更新现有函数时,即使我重新启动容器,它也永远不会注册芹菜。
这是我的dockerfile
:
# start with a base image
FROM python:3.4-slim
ENV REDIS_IP 1.1.1.111
ENV REDIS_PORT 6379
ENV REDIS_DB 0
# install dependencies
RUN apt-get update && apt-get install -y \
apt-utils \
nginx \
supervisor \
python3-pip \
&& rm -rf /var/lib/apt/lists/*
RUN echo "America/New_York" > /etc/timezone; dpkg-reconfigure -f noninteractive tzdata
# update working directories
ADD ./app /app
ADD ./config /config
ADD requirements.txt /
# install dependencies
RUN pip install --upgrade pip
RUN pip3 install -r requirements.txt
# setup config
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
RUN rm /etc/nginx/sites-enabled/default
RUN ln -s /config/nginx.conf /etc/nginx/sites-enabled/
RUN ln -s /config/supervisor.conf /etc/supervisor/conf.d/
EXPOSE 80
CMD ["supervisord", "-n"]
然后是我的supervisor.conf
:
[program:app]
command = uwsgi --ini /config/app.ini
autostart=true
autorestart=true
[program:nginx]
command = service nginx restart
autostart=true
autorestart=true
[program:celery]
directory = /app
command = celery -A tasks.celery worker -P eventlet -c 1000
autostart=true
autorestart=true
我的tasks.py
:
import os
from celery import Celery
from app import app as flask_app
def make_celery(app):
celery = Celery(app.import_name, backend='redis://{0}:{1}/{2}'.format(os.environ['REDIS_IP'],os.environ['REDIS_PORT'],os.environ['REDIS_DB']),
broker='redis://{0}:{1}/{2}'.format(os.environ['REDIS_IP'],os.environ['REDIS_PORT'],os.environ['REDIS_DB']))
celery.conf.update(
CELERY_ENABLE_UTC=True,
CELERY_TIMEZONE='America/New_York'
)
TaskBase = celery.Task
class ContextTask(TaskBase):
abstract = True
def __call__(self, *args, **kwargs):
with app.app_context():
return TaskBase.__call__(self, *args, **kwargs)
celery.Task = ContextTask
return celery
celery = make_celery(flask_app)
@celery.task()
def add_together(a, b):
return a+ b
@celery.task()
def multiply(a,b)
return a*b
由于某种原因:
multiply
从未注册,add_together
进行更改时,即使重新启动容器也不会注册。我正在用:
启动我的容器docker build --rm -t myapp .
docker run -d -p 88:80 -v $(pwd)/app:/app --name=myapp myapp
并重启:
docker restart myapp
我也试过
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
然后重新重建应用程序。什么都没有帮助。任何想法都会非常感激。
答案 0 :(得分:1)
我认为这可能是问题所在:
@celery.task() # <-- you shouldn't call this decorator directly
def add_together(a, b):
return a+ b
尝试将其更改为:
@celery.task
def add_together(a, b):
return a+ b
原因:只需查看source code of decorator task
:
def task(self, *args, **opts):
"""Creates new task class from any callable."""
# ... handling named options
if len(args) == 1:
if callable(args[0]):
return inner_create_task_cls(**opts)(*args)
raise TypeError('argument 1 to @task() must be a callable')
if args:
raise TypeError(
'@task() takes exactly 1 argument ({0} given)'.format(
sum([len(args), len(opts)])))
return inner_create_task_cls(**opts)
它接受的唯一未命名的参数是要装饰的函数。否则会引发TypeError
并被supervisord
吞并,因为您没有配置the loglevel
to debug
。
答案 1 :(得分:1)
我无法在我的设置上重现您的问题。我在Celery文档中创建了一个简单的Flask应用程序。
您可以尝试一些命令来仔细检查您的设置吗?
在myapp容器中打开一个shell(它必须已经在运行):
docker exec -t -i myapp /bin/bash
然后:
cd /app
celery -A tasks.celery status
celery -A tasks.celery inspect registered
新任务是否显示?
我认为你可能有其他celery实例连接到同一个redis服务器,这就是你有21个实例的原因。但我猜。
您也可以尝试使用独立的redis容器。
docker run --name myredis -d redis
在调试模式下执行celery,使用:
docker run --rm -t -i -v $(pwd)/app:/app -e REDIS_IP=myredis -u nobody -w /app --link myredis myapp celery -A tasks.celery worker -P eventlet -c 1000 -l debug
现在有任务吗?它应该只列出芹菜启动横幅消息。
我认为您的图片没有问题,但您可以仔细检查一下:
docker exec myapp /bin/bash -c "cat /app/tasks.py"
我不认为这是问题,因为您将/ app复制到图像中,当您运行容器时,您使用本地目录再次映射/ app。您是从构建容器的同一目录运行容器吗?
-v $(pwd)/ app:/ app将使用当前目录./app覆盖容器中的/ app。你真的需要这个吗?如果没有-v部分,你会得到相同的结果吗?
我希望找出错误是有帮助的。
答案 2 :(得分:1)
我制作了代码的工作回购。它存在here。
我改变的事情:
multiply
def)我没有专注于监督部分。