运行没有'-it'

时间:2018-02-04 10:27:07

标签: python docker httpserver

注意:我不是要在这里解决实际项目中的任何问题。这个问题仅用于理解我在下面第二个实验(实验2)中看到的结果背后的原因。

这些实验是在macOS High Sierra 10.13.1的macOS终端版本2.8上使用Docker版本17.12.0-ce进行的。

实验1:具有docker run选项

-it SimpleHTTPServer

这是我的Dockerfile

FROM python:2.7-slim
CMD ["python", "-m", "SimpleHTTPServer"]

我构建它并使用此命令运行它:

docker build -t pyhttp .
docker run -it -p 8000:8000 pyhttp

在另一个终端中,我使用以下命令测试容器:

curl http://localhost:8000/

curl命令产生预期结果:目录列表。在运行docker run的终端中,我看到了预期的输出。

$ docker run -it -p 8000:8000 pyhttp
Serving HTTP on 0.0.0.0 port 8000 ...
172.17.0.1 - - [04/Feb/2018 10:07:33] "GET / HTTP/1.1" 200 -

最后,按 Ctrl + C 停止此泊坞窗容器。

实验2:docker run SimpleHTTPServer没有-it选项

现在我使用此命令运行相同的pyhttp图像:

docker run -p 8000:8000 pyhttp

即使容器正在运行,终端上也不会出现输出。我没有看到预期的Serving HTTP on 0.0.0.0 port 8000 ...消息。

虽然如果我使用curl http://localhost:8000/测试容器,我会看到GET请求的日志显示在运行docker run的终端中。

$ docker run -p 8000:8000 pyhttp
172.17.0.1 - - [04/Feb/2018 10:12:41] "GET / HTTP/1.1" 200 -

问题:为什么没有出现初始Serving HTTP on 0.0.0.0 port 8000 ...消息,但会出现HTTP请求的后续日志?

实验3:docker run没有-it选项的烧瓶应用

我构建它并使用此命令运行它:

docker build -t flaskapp .
docker run -p 8000:8000 flaskapp

在另一个终端中,我使用以下命令测试容器:

curl http://localhost:8000/

在运行docker run的终端中,我看到了预期的输出。

$ docker run -p 8000:8000 flaskapp
 * Running on http://0.0.0.0:8000/ (Press CTRL+C to quit)
172.17.0.1 - - [04/Feb/2018 10:22:28] "GET / HTTP/1.1" 200 -

问题:为什么仅在实验2中,Serving HTTP on 0.0.0.0 port 8000 ...消息未出现?

1 个答案:

答案 0 :(得分:6)

python -m SimpleHTTPServer的第一行输出打印到stdout;其余行打印到stderr。考虑这些调用之间的区别:

njv@organon:~/tmp$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
172.17.2.26 - - [06/Feb/2018 20:55:52] "GET / HTTP/1.1" 200 -

njv@organon:~/tmp$ python -m SimpleHTTPServer  > /dev/null
172.17.2.26 - - [06/Feb/2018 20:56:26] "GET / HTTP/1.1" 200 -

第二个没有显示" Serving" line,因为stdout被丢弃,但两者都显示日志行,因为stderr不是。另一方面,Flask写出了#34;起始"登录到stderr(以及更多日志行):

njv@organon:~/tmp$ python flaskapp.py > /dev/null
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [06/Feb/2018 20:58:10] "GET / HTTP/1.1" 200 -

(从这里编辑)您的docker调用python时发生的事情是,如果没有-t选项,stdout将被完全缓冲,并且使用-t选项,它会被' s line-buffered,因此它会在每个换行符后立即出现。

$ docker help run|grep -- ' -t'
  -t, --tty                            Allocate a pseudo-TTY

我还在寻找一个明确的来源(this article看起来很有希望),但似乎在sys.stdout.isatty() is True时,python在行缓冲模式下打开stdout,因此,每条线都会在打印时显示,但如果没有,则以完全缓冲模式打开,因此仅在缓冲区已满时打印输出。