Docker - Импорт локального модуля на исполняемый скрипт Python - PullRequest
0 голосов
/ 19 июня 2019

Прежде всего, я относительно новичок в Docker, поэтому извините, если мой вопрос тупой или средний.

Я создаю мультиконтейнерное приложение, и у меня возникают проблемы с отображением одного из его сервисов, который отлично работает на локальном компьютере. Вот некоторые из моих особенностей Docker:

Docker Compose

version: '2'

services:
  dashboard:
    build: demo-dashboard/
    ports:
     - "8080:8080"
    environment:
      - ES_ENDPOINT_EXTERNAL=http://localhost:9200
      - http.cors.enabled=true
      - http.cors.allow-origin=ES_ENDPOINT_EXTERNAL
      - http.cors.allow-headers=Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With
      - http.cors.allow-credentials=true
    volumes:
     - ./demo-dashboard:/usr/src/app
    networks:
      - dashboard-network

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:6.7.0
    environment:
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - http.cors.enabled=true
      - http.cors.allow-origin=http://localhost:8080
      - http.cors.allow-headers=Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With
      - http.cors.allow-credentials=true
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    mem_limit: 1g
    cap_add:
      - IPC_LOCK
    volumes:
      - esdata1:/usr/share/elasticsearch/data
    networks:
      - dashboard-network
    ports:
      - 9200:9200

  orchestrator:
    image: orchestrator-mabsed
    build: orchestrator/
    volumes:
      - './orchestrator/tasks.py:/soneti/tasks.py'
    ports:
     - "8082:8082"
    environment:
      ES_HOST: 'elasticsearch'
    tty: true

volumes:
  esdata1:
    driver: local

networks:
  dashboard-network:
    driver: bridge

Служба, которая представляет проблему - это оркестратор, чей Dockerfile выглядит так:

FROM python:3.6

COPY requirements.txt .
RUN pip install --user -r requirements.txt

COPY tasks.py .
COPY detector/ .
COPY filter/ .
COPY lemmatizer/ .

COPY my_sched.py .
RUN python my_sched.py

my_sched.py - это файл планировщика, который запускается каждые 5 минут и запускает конвейер Luigi, содержащийся в файле tasks.py, проверяющий, выполнены ли определенные требования. Вот my_sched.py файл

import sched, time
import sys
import subprocess

s = sched.scheduler(time.time, time.sleep)

def cron():
    s.enter(5*60, 1, cron, [])
    command = '{} -m luigi --local-scheduler --module tasks Main'.format(sys.executable)
    output = subprocess.check_output(command.split(), shell= False)

s.enter(5, 1, cron, [])
s.run()

Проблема в том, что в tasks.py файле мне нужно импортировать компонент, содержащийся в моей локальной папке filter, и кажется, что контейнер Docker его не находит.

tasks.py часть импорта выглядит так:

import sys
sys.dont_write_bytecode = True

# orchestration
import luigi
from luigi.contrib.esindex import CopyToIndex
import datetime

# filter
import os
import csv
import json
from filter.filter import filter_spam

# lemmatizer
from lemmatizer.lemmatizer import lemmatize
from cube.api import Cube

# detection
sys.path.insert(0, './detector/')
from detect_events import main as detect_events

lemmatizer = Cube(verbose=True)
lemmatizer.load("es", tokenization=False, parsing=False)
...

Это вывод docker-compose up:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/local/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/root/.local/lib/python3.6/site-packages/luigi/__main__.py", line 20, in <module>
    luigi_run()
  File "/root/.local/lib/python3.6/site-packages/luigi/cmdline.py", line 9, in luigi_run
    run_with_retcodes(argv)
  File "/root/.local/lib/python3.6/site-packages/luigi/retcodes.py", line 70, in run_with_retcodes
    with luigi.cmdline_parser.CmdlineParser.global_instance(argv):
  File "/usr/local/lib/python3.6/contextlib.py", line 81, in __enter__
    return next(self.gen)
  File "/root/.local/lib/python3.6/site-packages/luigi/cmdline_parser.py", line 52, in global_instance
    new_value = CmdlineParser(cmdline_args)
  File "/root/.local/lib/python3.6/site-packages/luigi/cmdline_parser.py", line 64, in __init__
    self._attempt_load_module(known_args)
  File "/root/.local/lib/python3.6/site-packages/luigi/cmdline_parser.py", line 142, in _attempt_load_module
    __import__(module)
  File "/tasks.py", line 13, in <module>
    from filter.filter import filter_spam
ModuleNotFoundError: No module named 'filter.filter'; 'filter' is not a package
Traceback (most recent call last):
  File "my_sched.py", line 13, in <module>
    s.run()
  File "/usr/local/lib/python3.6/sched.py", line 154, in run
    action(*argument, **kwargs)
  File "my_sched.py", line 10, in cron
    output = subprocess.check_output(command.split(), shell= False)
  File "/usr/local/lib/python3.6/subprocess.py", line 356, in check_output
    **kwargs).stdout
  File "/usr/local/lib/python3.6/subprocess.py", line 438, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['/usr/local/bin/python', '-m', 'luigi', '--local-scheduler', '--module', 'tasks', 'Main']' returned non-zero exit status 1.
ERROR: Service 'orchestrator' failed to build: The command '/bin/sh -c python my_sched.py' returned a non-zero code: 1

Наконец, общее видение рабочего каталога может помочь:

MABSED/
|_ docker-compose.yml
|_ ...
|_ orchestrator/
   |_ requirements.txt
   |_ tasks.py
   |_ my_sched.py
   |_ data/
   |_ detector/
   |_ filter/
      |_ filter.py
      |_ __init__.py
   |_ lemmatizer/

Наконец, просто подчеркните, что модель отлично работает на локальном компьютере, и проблема заключается в попытке преобразовать ее в Docker.

1 Ответ

0 голосов
/ 19 июня 2019

Навигация по работающему контейнеру Я обнаружил, что папки не создавались должным образом, и я копировал только его содержимое, а не саму папку, поэтому путь filter.filter не существовал.

Возможное решение - отредактировать сервисный Dockerfile и скопировать все в одну команду вместо файла за файлом, например:

COPY . /

или если вы не хотите копировать все файлы и только определенные папки, вы можете решить эту проблему, указав папку в целевом пути:

COPY filter/ filter/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...