简体   繁体   中英

How to stream Docker container logs via the Go SDK

I'm writing a tool for some game server software in Go called sampctl and the primary function is to spin up a Docker container for a server instance and then capture the logs coming out of the container, clean them up a bit and send them to a location of the users choice such as Elasticsearch or an administration panel for later analysis.

I've got everything else working, the only thing I can't seem to get to work is streaming logs. I can get logs if the application in the container crashes but I want to stream the logs in realtime.

I've tried using a scanner with the ContainerLogs returned ReadCloser but that just hung at the terminal.

https://github.com/Southclaws/sampctl/blob/9c76b4dd1b3dbb9e18927da10028d5beeb94f728/run_container.go#L64-L67

Does ContainerLogs even support streaming? Or will I need to figure out another solution...

Apologies if this is more of a Go question than a Docker question, I wasn't too sure whether or not to post here or on GoLangBridge...

Have you read the docs? The stream has metadata embedded, so you can't quite just pipe it to the console.

I have the following code in a monitoring application:

    i, err := cli.ContainerLogs(context.Background(), cid, types.ContainerLogsOptions{
        ShowStderr: true,
        ShowStdout: true,
        Timestamps: false,
        Follow:     true,
        Tail:       "40",
    })
    if err != nil {
        log.Fatal(err)
    }
    hdr := make([]byte, 8)
    for {
        _, err := i.Read(hdr)
        if err != nil {
            log.Fatal(err)
        }
        var w io.Writer
        switch hdr[0] {
        case 1:
            w = os.Stdout
        default:
            w = os.Stderr
        }
        count := binary.BigEndian.Uint32(hdr[4:])
        dat := make([]byte, count)
        _, err = i.Read(dat)
        fmt.Fprint(w, string(dat))
    }

It streams as long as I keep it running. There is also this helper package to do most of that for you, but in my case I need to handle the messages individually like this for other reasons.

Okay, I managed to resolve this and I'm not sure why captncraig's answer didn't work which I'm still curious about but hey, here's my solution:

I had to set some other options in my ContainerCreate call:

        Tty:          true,
        AttachStdout: true,
        AttachStderr: true,

Then the scanner.Scan() method worked perfectly!

Here is the updated code: https://github.com/Southclaws/sampctl/blob/1ad7971d817031bd5a5b3acfad3bf2ea69232c98/run_container.go#L56-L70

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