簡體   English   中英

為什么Dramatiq無法在Docker容器中啟動?

[英]Why does Dramatiq fail to start in Docker-container?

我正在嘗試使用Dramatiq作為工作人員庫來執行分布式任務隊列Django項目。 從開發環境中執行項目時,我能夠在沒有錯誤的情況下運行項目,但是在嘗試運行內置的docker-container時卻得到了神秘的FileNotFoundError。 我已經就為什么會發生這種情況提出了一些想法。

錯誤的回溯是:

Traceback (most recent call last):
  File "manage.py", line 15, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.5/dist-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.5/dist-packages/django/core/management/__init__.py", line 365, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.5/dist-packages/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.5/dist-packages/django/core/management/base.py", line 335, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python3.5/dist-packages/django_dramatiq/management/commands/rundramatiq.py", line 83, in handle
    os.execvp(executable_path, process_args)
  File "/usr/lib/python3.5/os.py", line 615, in execvp
    _execvpe(file, args)
  File "/usr/lib/python3.5/os.py", line 660, in _execvpe
    raise last_exc.with_traceback(tb)
  File "/usr/lib/python3.5/os.py", line 650, in _execvpe
    exec_func(fullname, *argrest)
FileNotFoundError: [Errno 2] No such file or directory

我用一個Dramatiq任務制作了一個簡單的Django項目,以重現該問題。 可以從以下位置克隆該存儲庫: https : //bitbucket.org/AvareaToniN/dramatiqexample/src/master/ ,以下是該存儲庫的相關部分:

dramatiqexample
│   .gitignore
│   circus.ini
│   Dockerfile
│   entrypoint.sh
│   manage.py
│   requirements.txt
│
├───dramatiqexample
│       settings.py
│       urls.py
│       wsgi.py
│       __init__.py
│
└───exampleapp
    │   admin.py
    │   apps.py
    │   models.py
    │   tasks.py
    │   tests.py
    │   views.py
    │   __init__.py
    │
    └───migrations
            __init__.py

要求

# requirements.txt
Django==2.0.7
dramatiq[redis, watch]
django_dramatiq==0.4.0
apscheduler==3.5.1

馬戲團配置

# circus.ini
[circus]
check_delay = 5

[watcher:gunicorn]
cmd = /usr/local/bin/gunicorn
args = -b 0.0.0.0:8000 -w 2 dramatiqexample.wsgi
numprocesses = 1
autostart = true
max_retry = -1
priority = 500

[watcher:dramatiq]
cmd = python
args = manage.py rundramatiq --processes 6 --no-reload --path ./dramatiqexample
autostart = true
max_retry = -1
priority = 50

[watcher:redis]
cmd = redis-server
autostart = true
max_retry = -1
priority = 200

[env:redis]
PATH = $PATH: /usr/local/bin/

Dockerfile

FROM ubuntu:16.04

RUN apt-get update && apt-get install -y software-properties-common curl \
    && add-apt-repository ppa:ubuntugis/ubuntugis-unstable \
    && apt-get update \
    && apt-get install -y \
    python3-pip \
    libssl-dev \
    libffi-dev \
    libzmq-dev \
    libevent-dev \
    python3-gdal \
    gcc \
    g++ \
    build-essential \
    openssl \
    nginx \
    apt-transport-https \
    wget \
    && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 \
    && update-alternatives --install /usr/bin/pip    pip    /usr/bin/pip3    10 \
    && rm -rf /var/lib/apt/lists/*

# redis
RUN wget http://download.redis.io/redis-stable.tar.gz
RUN tar xvzf redis-stable.tar.gz
WORKDIR redis-stable
RUN make
RUN make install
WORKDIR /
# End of redis

RUN echo openssl version

RUN pip install pip --upgrade
#https://github.com/circus-tent/circus/issues/1056
RUN pip install 'tornado==4.5.3'
RUN pip install gunicorn circus

ADD requirements.txt /

RUN pip install -r requirements.txt
ADD . /
RUN python manage.py makemigrations
RUN python manage.py migrate
RUN python manage.py collectstatic --noinput

EXPOSE 8000

RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh

#!/bin/bash

exec circusd circus.ini --log-level debug

exec "$@";

Django的設置:

# dramatiqexample/settings.py
import os
import redis
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'm7m$2#nre09wdf(jbe%#h+3o9l8j_%v7h87cc!rd@ow6tfy=-1'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django_dramatiq',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'exampleapp.apps.ExampleappConfig',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'dramatiqexample.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'dramatiqexample.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/

PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles')
STATIC_URL = '/static/'

# DRAMATIQ CONFIG
DRAMATIQ_REDIS_URL = os.getenv('REDIS_URL', 'redis://127.0.0.1:6379/0')
DRAMATIQ_BROKER = {
    "BROKER": "dramatiq.brokers.redis.RedisBroker",
    "OPTIONS": {
        "connection_pool": redis.ConnectionPool.from_url(DRAMATIQ_REDIS_URL),
    },
    "MIDDLEWARE": [
        "dramatiq.middleware.Prometheus",
        "dramatiq.middleware.AgeLimit",
        "dramatiq.middleware.TimeLimit",
        "dramatiq.middleware.Callbacks",
        "dramatiq.middleware.Retries",
        "django_dramatiq.middleware.AdminMiddleware",
        "django_dramatiq.middleware.DbConnectionsMiddleware",
    ]
}

# Defines which database should be used to persist Task objects when the
# AdminMiddleware is enabled.  The default value is "default".
DRAMATIQ_TASKS_DATABASE = "default"

網址

#dramatiqexample/urls.py
from django.contrib import admin
from django.urls import path

from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from exampleapp.tasks import minutely_tasks

urlpatterns = [
    path('admin/', admin.site.urls),

]

# https://stackoverflow.com/questions/9259844/running-startup-code-right-after-django-settings-also-for-commands
SCHEDULER = BackgroundScheduler()
SCHEDULER.add_job(
    minutely_tasks.send,
    CronTrigger.from_crontab("* * * * *"),
)
try:
    SCHEDULER.start()
except KeyboardInterrupt:
    SCHEDULER.shutdown()

測試任務

# exampleapp/tasks.py
import dramatiq
import logging
from datetime import datetime

logger = logging.getLogger(__name__)

@dramatiq.actor
def minutely_tasks():
    logger.warning(datetime.now())

在IDE中,命令“ python manage.py runserver”和“ python manage.py rundramatiq”可以正常工作,但是由於某些原因,它們無法通過dockerized馬戲團進程失敗。

我遇到同樣的問題。 這是與戲劇安裝有關的問題。 實際上,就我而言,該腳本將在/ usr / local / lib中時在/ usr / lib中執行“ dramatiq”文件。 所以我找到了一個解決方案:創建一個虛擬環境。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM