запуск Docker SDK из Gunicorn / Nginx WSGI API Ошибка разрешения - PullRequest
0 голосов
/ 04 января 2019

Я пишу Flask API, который вызывает Docker-контейнеры, которые выполняют сценарии очистки веб-страниц Selenium. Я проверил это в dev, и он работает нормально (python3 -m run flask host = 0.0.0.0), и я убедился, что пользователь (ubuntu) находится в группе docker, и группа была сброшена (newgrp docker), однако его все еще получает ошибку разрешения при попытке запустить. Я проверил PID, и пользователь ubuntu для процесса gunicorn, изображение доступно в Docker, что еще может потребоваться для предоставления разрешения? Код моей колбы ниже

import docker
import os
from flask import Flask, render_template

app = Flask(__name__)


@app.route('/civitek/<f_name>/<l_name>/<ref_url>')
def civitek(f_name, l_name, ref_url):
    client = docker.from_env()
    container = client.containers.create('qxf2rohand/qxf2_pom_essentials',command="/bin/bash", environment=["F_NAME={}".format(f_name), "L_NAME={}".format(l_name),"REF_URL={}".format(ref_url)], volumes={os.path.join(os.getcwd(),'florida'):{'bind':'/florida','mode':'rw'}}, stdin_open=True, auto_remove=False)
    container.start()
    container.exec_run('pip install pytz selenium pillow captcha2upload pyvirtualdisplay requests')
    container.exec_run('python florida/civitek_scraper.py')
    civi = open(str(os.path.join(os.getcwd(),'florida/output/output.html')))
    output = civi.read()
    container.stop()
    container.remove()
    return output

@app.route('/indiana/<ref_url>')
def indiana(ref_url):
    client = docker.from_env()
    container = client.containers.create('qxf2rohand/qxf2_pom_essentials',command="/bin/bash", environment=["REF_URL={}".format(ref_url)], volumes={os.path.join(os.getcwd(),'indiana'):{'bind':'/indiana','mode':'rw'}}, stdin_open=True, auto_remove=False)
    container.start()
    container.exec_run('pip install pytz selenium bs4 pyvirtualdisplay requests')
    container.exec_run('python indiana/in_scraper.py')
    indy = open(str(os.path.join(os.getcwd(),'indiana/output/output.html')))
    output = indy.read()
    container.stop()
    container.remove()
    return render_template('in_master_template.html', results=output)

if __name__ == '__main__':
    app.run()

1 Ответ

0 голосов
/ 04 января 2019

Код, который вы показываете, должен быть чрезвычайно простым для установки без использования Docker, так как вы запускаете код Python из скрипта Python. Вы должны добавить длинный список пакетов pip, которые вы устанавливаете, в файл setup.py или requirements.txt вашего собственного приложения, а затем использовать обычный модуль subprocess для запуска сценариев:

@app.route('/civitek/<f_name>/<l_name>/<ref_url>')
def civitek(f_name, l_name, ref_url):
  p = subprocess.run([sys.executable, './florida/civitek_scraper.py'],
                     env={'F_NAME': f_name, 'L_NAME': l_name, 'REF_URL': ref_url})
  with open('florida/output/output.html') as f:
    return f.read()

(При использовании sys.executable здесь будет использоваться тот же Python в вашей активной виртуальной среде; он не обязательно должен быть первым Python в $PATH.)

Добавление Docker к этому добавляет огромное количество сложностей и соображений безопасности: если вы ошиблись, вы открываете возможность очень простого удаленного эксплойта root.

Если вы получаете ошибки разрешения, у вашего пользователя или группы нет разрешения на доступ к файлу сокета Docker. Проверьте вывод id и ls -l /var/run/docker.sock.

Использование exec, которое вы показываете, и установка нового программного обеспечения в контейнер после запуска являются анти-шаблонами. (Должен ли ваш HTTP-запрос просто завершиться неудачей, если packages.python.org имеет временное отключение?) Напишите пользовательский образ Docker, который включает в себя все зависимости для вашего скрипта, и запустите этот скрипт в качестве основного процесса контейнера, если вам нужно запустить это в контейнере вообще.

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