python - 在没有 '-it' 的情况下运行容器时只出现一行 SimpleHTTPServer 输出

标签 python docker httpserver

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

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

实验一:docker run SimpleHTTPServer with -it options

这是我的 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 停止这个 docker 容器。

实验 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 运行.

$ 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 选项的 Flask 应用

我用这个命令构建并运行它:

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 ...消息没有出现?

最佳答案

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”行,因为 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 -

(从此处编辑)您对 python 的 docker 调用发生的情况是,如果没有 -t 选项,stdout 是完全缓冲的,并且使用 -t 选项,它是行缓冲的,因此它会立即出现在每个换行符之后。

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

我仍在寻找这方面的明确来源(this article 看起来很有希望),但似乎当 sys.stdout.isatty() 为 True 时,python 会打开 stdout 在行缓冲模式下,因此每一行都在打印时显示,但如果不是,它会以完全缓冲模式打开,因此只有在缓冲区已满时才会打印输出。

关于python - 在没有 '-it' 的情况下运行容器时只出现一行 SimpleHTTPServer 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48607096/

相关文章:

java - Spring 代理 : Error opening zip file or JAR manifest missing

javascript - moment.isoWeekday 不是函数

Python 请求 : Measure time waiting for response

python - 在 BeautifulSoup 中查找特定属性

python - 检查一组坐标与另一组坐标的接近程度

docker - 如何在Windows中为docker工具箱设置注册表镜像

python - pip install google-cloud-pubsub 在 docker 容器中安装失败

Windows Django 服务器

html - 为什么服务器返回的 HTML 页面没有在浏览器中呈现

python - 使用boto3将文件上传到S3