首页 > 解决方案 > 是否可以在单个进程中运行烧瓶?(解决 ipdb 和 Docker ttys 的明显问题)

问题描述

我有一个烧瓶应用程序,我正在像这样运行:

flask run --host=0.0.0.0

当我查看进程列表时,我看到:

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 23:48 pts/0        00:00:00 /bin/sh -c flask run --host=0.0.0.0
root         6     1  1 23:48 pts/0        00:00:01 /usr/local/bin/python /usr/local/bin/flask run --host=0.0.0.0
root         8     6  3 23:48 pts/0        00:00:02 /usr/local/bin/python /usr/local/bin/flask run --host=0.0.0.0

三个过程。

如果我使用--without-threads同样的三个进程运行:

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 00:28 pts/0    00:00:00 /bin/sh -c flask run --host=0.0.0.0 --without-threads
root         6     1  2 00:28 pts/0    00:00:02 /usr/local/bin/python /usr/local/bin/flask run --host=0.0.0.0 --without-threads
root         8     6  4 00:28 pts/0    00:00:04 /usr/local/bin/python /usr/local/bin/flask run --host=0.0.0.0 --without-threads

有没有办法以某种方式将烧瓶作为单个进程运行?

动机

有问题的烧瓶应用程序在 docker 容器内运行。我希望能够使用ipdb.

我观察到,如果我在我的 docker-compose 文件中设置它:

    stdin_open: true
    tty: true

并运行一个简单的单进程 python 应用程序,而不是烧瓶应用程序......

$ docker exec -it bug_demo_bug_demo_1 bash
root@98245482089b:/opt/bug_demo/bug_demo# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 00:41 pts/0    00:00:00 /bin/sh -c python app.py
root         7     1 20 00:41 pts/0    00:00:00 python app.py

...并在应用程序处于断点时附加到容器,我可以ibpd正常进入并使用它 - 箭头键和选项卡完成正常工作。

但是,当我尝试对烧瓶应用程序执行相同操作时(在应用程序在断点中等待时附加到容器),事情就无法正常工作。

要么我禁用tty: truein docker-compose.yml,并且可以使用 useipdb但没有箭头键和制表符完成,要么我留tty: true在原地,但根本不能真正使用ipdb,b/c 似乎tty连接到所有三个烧瓶进程,导致除了单个字符命令得到乱码。(尽管我可以通过此设置看到箭头键和制表符完成工作。)

所有这些让我相信,如果我能找到一种方法将我的烧瓶应用程序作为单个进程运行,我将能够附加到 docker 容器并ipdb根据需要使用。

有没有办法做到这一点?

更新:问题在启动期间出现,而不是在请求处理期间

经过进一步检查,我发现此问题仅在“启动”代码期间出现。例如:如果断点在create_app函数内部。

如果断点位于请求处理程序方法或从请求处理程序调用的代码中,则一切都按预期工作。

使用exec将进程计数从三个减少到两个(根进程被第一个工作人员替换),但问题仍然体现在create_app.

运行 flask with--no-reload会使第二个工作人员离开,因此进程计数可以被强制为一或两个,然后不使用或使用exec。对于我的用例来说,运行 with--no-reload并不理想,但它确实使问题消失了,即使对于create_app.

出于我的目的,我可以忍受ipdb只能在请求处理程序中使用终端的限制——我不希望从启动代码中运行调试器。(但我仍然会接受答案并愉快地奖励赏金,如果有人能准确解释启动代码断点案例中发生的事情,以及为什么问题没有在请求处理程序断点案例中体现。)

根据这一--no-reload发现,确实感觉潜在的脆弱性与请求处理过程和代码重新加载过程“共享”的 TTY 有某种关系。

Flask 和 Docker 版本信息

ipdb> flask.__version__
'1.0.3'
$ docker version
Client: Docker Engine - Community
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        6247962
 Built:             Sun Feb 10 04:12:39 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 04:13:06 2019
  OS/Arch:          linux/amd64
  Experimental:     false
$ docker info
Containers: 22
 Running: 3
 Paused: 0
 Stopped: 19
Images: 362
Server Version: 18.09.2
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 9754871865f7fe2f4e74d43e2fc7ccd237edcbce
runc version: 09c8266bf2fcf9519a651b04ae54c967b9ab86ec
init version: fec3683
Security Options:
 seccomp
  Profile: default
Kernel Version: 4.9.125-linuxkit
Operating System: Docker for Mac
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 3.855GiB
Name: linuxkit-025000000001
ID: ZAK2:V2VU:IZFF:6MQQ:IFJB:2ZKY:VHA5:CSO3:VXQQ:UK6C:O3I7:S3ZU
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): true
 File Descriptors: 59
 Goroutines: 89
 System Time: 2019-07-28T14:00:38.3184372Z
 EventsListeners: 2
HTTP Proxy: gateway.docker.internal:3128
HTTPS Proxy: gateway.docker.internal:3129
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false
Product License: Community Engine
$ docker-compose --version
docker-compose version 1.23.2, build 1110ad01

标签: pythondockerflask

解决方案


要使烧瓶在单个处理器中运行,请使用以下命令

if __name__ == '__main__':
    app.run(threaded=False, processes=1)

推荐阅读