标准输出缓冲在docker集装箱中

我不完全确定这里发生了什么,但是当我在一个容器中运行我的代码时,似乎stdout被缓冲了,但是如果我在主机或OSX上运行它,则不会。

https://github.com/myles-mcdonnell/procwrap/blob/master/procwrap.go

相关部分(为简洁起见):

cmd := exec.Command("ping", "127.0.0.1") logger := &lumberjack.Logger{ Filename: conf.LogFile, MaxSize: conf.MaxLogSizeMb, MaxBackups: conf.MaxLogBackups, MaxAge: conf.MaxLogAgeDays, } cmd.Stdout = io.MultiWriter(os.Stdout, logger) err := cmd.Run() 

在一个容器中运行的subprocess运行良好,但我只看到输出(到标准输出和日志文件)的间隔,如缓冲区正在刷新。 在容器外部运行它,并在生成时输出。 我正在使用去1.6.3。 我看到相同的行为交互式地在后台运行容器。

Docker版本:

 Client: Version: 1.10.3 API version: 1.22 Go version: go1.5.3 Git commit: 20f81dd Built: Thu Mar 10 21:49:11 2016 OS/Arch: darwin/amd64 Server: Version: 1.12.0 API version: 1.24 Go version: go1.6.3 Git commit: 8eab29e Built: Thu Jul 28 23:54:00 2016 OS/Arch: linux/amd64 

=======更新======

我看到基于基础图像的不同行为。 在debian上运行procwrap:wheezy base得到缓冲输出。 在Ubuntu上做同样的事情:值得信赖的是它是同步的。 下面的Dockerfiles,只需执行“docker run {image_name}”即可。 在wheezy VM上运行procwrap(不涉及docker)不会缓冲输出。

可靠:

 FROM ubuntu:trusty RUN apt-get update RUN apt-get install -y curl RUN apt-get install -y git RUN curl -O https://storage.googleapis.com/golang/go1.6.3.linux-amd64.tar.gz RUN tar -xvf go1.6.3.linux-amd64.tar.gz RUN mv go /usr/local ENV GOROOT=/usr/local/go RUN mkdir -p /go/src/github.com/myles-mcdonnell ENV GOPATH=/go ENV PATH=$PATH:$GOPATH/bin:$GOROOT/bin RUN go get github.com/myles-mcdonnell/procwrap WORKDIR /go/src/github.com/myles-mcdonnell/procwrap CMD procwrap -v 

喘息:

 FROM debian:wheezy RUN apt-get update RUN apt-get install -y curl RUN apt-get install -y git RUN curl -O https://storage.googleapis.com/golang/go1.6.3.linux-amd64.tar.gz RUN tar -xvf go1.6.3.linux-amd64.tar.gz RUN mv go /usr/local ENV GOROOT=/usr/local/go RUN mkdir -p /go/src/github.com/myles-mcdonnell ENV GOPATH=/go ENV PATH=$PATH:$GOPATH/bin:$GOROOT/bin RUN go get github.com/myles-mcdonnell/procwrap WORKDIR /go/src/github.com/myles-mcdonnell/procwrap CMD procwrap -v 

我面临同样的问题,看起来像根本原因是“stdout缓冲”。 如果还有其他问题,您可以阅读http://www.pixelbeat.org/programming/stdio_buffering/和google。 我无法通过“stdbuf”或任何Linux /应用程序设置来解决它,并更改了我想要dockerize控制台应用程序的源代码,以在每次写入时进行文件刷新。

(我的configuration很奇怪,原因很多,但它是:应用程序已经将日志输出configuration到名为“/ dev / stdout”的文件中,并且它在每个日志写入上执行file_flush,并且docker可以实时显示“docker日志-f XXXXX“)

这是你问的吗?

为什么我看到我的输出块? 它被缓冲和刷新的地方?

是。 您的Docker容器在Docker引擎上运行(可能由Docker计算机包装),您的命令正在从客户端运行。 即使您的引擎是在本地安装的,并且以交互模式运行您的容器,您input的命令和您看到的输出仍然基本上是针对localhost的HTTP请求的结果。 (或Unix Socket或TTY通信。)(我正在简化。)Docker通过networking驱动程序路由I / O,即它的标准输出必须刷新到(虚拟)networking连接,然后客户端将刷新你的标准输出。

在后台模式下,引擎会捕获stdout( 默认情况下 )写入文件。 docker logs命令将来自客户端的请求发送到引擎,引擎通过回读该文件的内容进行响应。