简体   繁体   中英

Why `docker run -t` could make python flush the output buffer?

1.

Dockerfile:

FROM python:3
CMD ["python", "-m", "http.server"]

When I execute next, you can see there is no log could be seen.

shubuntu1@shubuntu1:~/77$ docker build -t a:1 . --no-cache
...
Successfully tagged a:1
shubuntu1@shubuntu1:~/77$ docker run -d --name test a:1
9638189c0528fc98524b0b2f7bec72269186a3445795f0fcf974751a0d908f44
shubuntu1@shubuntu1:~/77$ docker logs test
shubuntu1@shubuntu1:~/77$

2.

I struggle against above for sometime & finally find it's because of the program buffer issue, so I can fix with next:

Dockerfile:

FROM python:3
CMD ["python", "-u", "-m", "http.server"]

Works now with -u :

shubuntu1@shubuntu1:~/77$ docker build -t a:1 . --no-cache
...
Successfully tagged a:1
shubuntu1@shubuntu1:~/77$ docker rm -f test
test
shubuntu1@shubuntu1:~/77$ docker run -d --name test a:1
68bc759a54ec3218b39e51404495a28d010a798b1d1e160ec7f68be3b18da9c7
shubuntu1@shubuntu1:~/77$ docker logs test
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

3.

But when I rollback the Dockerfile with situation 1:

Dockerfile:

FROM python:3
CMD ["python", "-m", "http.server"]

I find with -t in docker run , the buffer also flush as next:

shubuntu1@shubuntu1:~/77$ docker build -t a:1 . --no-cache
...
Successfully tagged a:1
shubuntu1@shubuntu1:~/77$ docker rm -f test
test
shubuntu1@shubuntu1:~/77$ docker run -dt --name test a:1
f7cd1b5b3c272ff42c7aecd251e324b70030c046489048370689ba25b33191cc
shubuntu1@shubuntu1:~/77$ docker logs test
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

So, my question is: why -t have this effect?

Running a docker container with -t/--tty appears to attach a pseudo-terminal to the process in the container.

If an stdout descriptor is attached to a terminal, it is line buffered.
It is assumed that a user is monitoring the terminal for output of the process; printing data frequently is considered important. The buffer is flushed as soon as a newline ( \\n ) character is encountered, the buffer fills up, or the process ends.

If stdout is attached to something different than a terminal, the stream is fully (or block) buffered. On libc/glibc, the default buffer size is 4096 bytes. The buffer must fill up before the its contents are flushed.
This reduces the number of expensive write system calls when it is assumed that data written to stdout will be examined later (eg log files).

See also Stdout Buffering by Evan Klitzke, Buffering in standard streams by Pádraig Brady and the stdout man page .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM