没有'-it'运行容器时,只出现一行SimpleHTTPServer输出

Lon*_*ner 8 python httpserver docker

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

这些实验使用Docker版本17.12.0-ce在macOS Terminal版本2.8上的macOS High Sierra 10.13.1上进行.

实验1:docker run带有-it选项的SimpleHTTPServer

这是我的Dockerfile:

FROM python:2.7-slim
CMD ["python", "-m", "SimpleHTTPServer"]
Run Code Online (Sandbox Code Playgroud)

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

docker build -t pyhttp .
docker run -it -p 8000:8000 pyhttp
Run Code Online (Sandbox Code Playgroud)

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

curl http://localhost:8000/
Run Code Online (Sandbox Code Playgroud)

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 -
Run Code Online (Sandbox Code Playgroud)

最后,按Ctrl+键停止此docker容器C.

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

现在我pyhttp用这个命令运行相同的图像:

docker run -p 8000:8000 pyhttp
Run Code Online (Sandbox Code Playgroud)

即使容器正在运行,终端上也不会显示输出.我没有看到预期的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 -
Run Code Online (Sandbox Code Playgroud)

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

实验3:docker run没有-it选项的Flask app

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

docker build -t flaskapp .
docker run -p 8000:8000 flaskapp
Run Code Online (Sandbox Code Playgroud)

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

curl http://localhost:8000/
Run Code Online (Sandbox Code Playgroud)

在终端运行中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 -
Run Code Online (Sandbox Code Playgroud)

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

Nat*_*eks 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 -
Run Code Online (Sandbox Code Playgroud)

第二个没有显示"服务"行,因为stdout被丢弃,但两者都显示日志行,因为stderr不是.另一方面,Flask将其"开始"日志写入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 -
Run Code Online (Sandbox Code Playgroud)

(从这里编辑)你的docker调用python时发生的事情是没有-t选项,stdout是完全缓冲的,并且使用该-t选项,它是行缓冲的,因此它会在每个换行符后立即出现.

$ docker help run|grep -- ' -t'
  -t, --tty                            Allocate a pseudo-TTY
Run Code Online (Sandbox Code Playgroud)

我仍然在寻找一个明确的来源(这篇文章看起来很有希望),但是看起来,当sys.stdout.isatty() is Truepython stdout在行缓冲模式下打开时,每行显示为它的打印,但是当它不是时,它会完全打开缓冲模式,因此仅在缓冲区满时打印输出.