stdout在docker容器中缓冲

Myl*_*ell 6 go 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()
Run Code Online (Sandbox Code Playgroud)

在容器中运行子进程运行正常,但我只是间隔地看到输出(到stdout和日志文件),就像刷新缓冲区一样.在容器外部运行它,并在生成时输出.我正在使用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
Run Code Online (Sandbox Code Playgroud)

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

我看到基于基本图像的不同行为.在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
Run Code Online (Sandbox Code Playgroud)

喘息:

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

Kon*_*tin 5

我遇到了同样的问题,看起来根本原因是“标准输出缓冲”。如果有任何其他问题,您可以开始阅读http://www.pixelbeat.org/programming/stdio_buffering/和谷歌。我无法通过“stdbuf”或任何 linux/app 设置来解决它,并更改了我想要 dockerize 的控制台应用程序的源代码,以便在每次写入时继续进行文件刷新。

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


Jes*_*ano 3

你问的是这个吗?

为什么我看到的输出是大块的?它是否在某处被缓冲和刷新?

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

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