Reputation: 1940
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.
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...
Upvotes: 10
Views: 8157
Reputation: 1940
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
Upvotes: 7
Reputation: 23108
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.
Upvotes: 15