2016-10-19 75 views
2

我想在码头集装箱内运行芹菜,并且由于某种原因它永远不会更新。每当我在tasks.py中添加新函数或更新现有函数时,即使在重新启动容器后,它也不会向芹菜注册。奇怪的码头+芹菜Bug

这里是我的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 

,由于某种原因:

  • 我有21名工人登记和multiply永远不会被注册,
  • 还当我修改add_together,甚至当我重新启动容器,从来没有登记为好,。

enter image description here

我开始我的容器:

docker build --rm -t myapp . 
docker run -d -p 88:80 -v $(pwd)/app:/app --name=myapp myapp 

和restart:

docker restart myapp 

我也曾尝试

docker stop $(docker ps -a -q) 
docker rm $(docker ps -a -q) 

,然后重新整个应用程序。没什么帮助。任何想法都会非常赞赏。

+0

你用'--no-cache'重建了吗? – user2915097

+0

@ user2915097我在https://docs.docker.com/engine/reference/commandline/build/上得到'unknown flag:--no-cache' – Jonathan

+0

我看到了--no-cache在构建image – user2915097

回答

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) 

唯一的无名它接受的论点是要装饰的功能。否则,由于您没有配置the loglevel to debug,因此会引起TypeError并被supervisord吞噬。

+0

嗨@Philip,感谢您的提示,但这不会有帮助。 – Jonathan

+1

@Jonathan你是否通过配置日志级别和日志文件获得了一些输出? –

1

我无法在我的设置中重现您的问题。我在Celery文档中创建了一个简单的Flask应用程序。

你可以尝试一些命令来仔细检查你的设置?

打开一个外壳到MYAPP容器(必须是已经运行):

docker exec -t -i myapp /bin/bash 

然后:

cd /app 
celery -A tasks.celery status 
celery -A tasks.celery inspect registered 

请问新的任务来了吗?

我想你可能有其他芹菜实例连接到同一个redis服务器,这就是为什么你有21个实例。但我猜。

您还可以尝试使用独立的redis容器。

docker run --name myredis -d redis 

而在调试模式下执行芹菜,具有:

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。你是从你建造容器的同一目录运行容器吗?

-v $(pwd)/ app:/ app将覆盖当前目录./app容器中的/ app。你真的需要这个吗?没有-v部分,你有相同的结果吗?

我希望能找出有什么不对的地方。

1

我做了一个代码的工作回购。它的生活here

事情我改变:

  • 结肠错字(看你multiply DEF)
  • 不调用装饰
  • 通用代码清理
  • 使用单一Redis的URI
  • 一些目录导航我的测试

我没有专注于supervisord部分。