【问题标题】:running Docker SDK from Gunicorn/Nginx WSGI API Permission error从 Gunicorn/Nginx WSGI API 权限错误运行 Docker SDK
【发布时间】:2019-01-05 03:55:15
【问题描述】:

我正在编写一个 Flask API,它调用执行 Selenium Web 抓取脚本的 docker 容器。我已经在 dev 中对此进行了测试,它工作正常(python3 -m run flask host=0.0.0.0)并且我确保用户(ubuntu)在 docker 组中并且该组已被重置(newgrp docker)但是它尝试运行时仍然出现权限错误。我已经检查了 PID 并且用户是 gunicorn 进程的 ubuntu,图像在 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()

【问题讨论】:

    标签: python docker flask


    【解决方案1】:

    您展示的代码在不使用 Docker 的情况下设置起来应该非常简单,因为您是从 Python 脚本运行 Python 代码。您应该将要安装的一长串 pip 包添加到您自己的应用程序的 setup.pyrequirements.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;它不一定是$PATH 中的第一个Python。)

    向其中添加 Docker 会增加大量的复杂性和安全性考虑:如果您弄错了,那么您就有可能进行非常直接的远程 root 漏洞利用。

    如果您收到权限错误,则说明您的用户或组无权访问 Docker 套接字文件。检查idls -l /var/run/docker.sock的输出。

    您展示的exec 的使用和启动后在容器中安装新软件都是反模式。 (如果 packages.python.org 临时中断,您的 HTTP 请求是否会失败?)编写一个自定义 Docker 映像,其中包含脚本的所有依赖项,然后将该脚本作为主容器进程运行,如果您需要运行它完全在容器中。

    【讨论】:

    • 谢谢大卫,我试图使其符合您的方法(这确实更有意义)但现在返回的 html 都被打乱了,不幸的是我将不得不尝试确定原因。 docker 方法仍然有效,但我唯一可用的服务器是开发服务器。我不太担心安全性,因为请求只会来自我组织内的一系列 IP。由于我的工作速度的性质是必需的,所以我目前正在使用外部 docker 映像,稍后将构建我自己的。我将尝试重建产品服务器并探索用户问题,我会回复您
    • 我能够通过手动 chmod rw=a 为 docker.sock 获得 docker 方法。出于 David 提到的安全考虑和更精简的代码,我将更改此 API。
    猜你喜欢
    • 2017-04-17
    • 2020-12-04
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 2021-08-27
    • 1970-01-01
    相关资源
    最近更新 更多