Guillaume Barré
Guillaume Barré

Reputation: 4218

go-docker client get container logs every seconds returns nothing

I'm using the docker.io/go-docker package to launch a container with GO. I'm able to get all the logs of the container once its main method returns

if err := cli.ContainerStart(context.Background(), resp.ID, types.ContainerStartOptions{}); err != nil {
    panic(err)
}

statusCh, errCh = cli.ContainerWait(context.Background(), resp.ID, container.WaitConditionNotRunning)

select {
    case err := <-errCh:
        if err != nil {
            panic(err)
        }
    case <-statusCh:
}

out, err := cli.ContainerLogs(context.Background(), resp.ID, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true})
if err != nil {
    panic(err)
}
// Do something with the logs here...

The trick is that the main method execution takes a while and I want to show the container logs to the user every seconds. My idea was to start a new goroutine to loop and make a request on cli.ContainerLogs.

So I changed my implementation to this :

nowUTC := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)

if err := cli.ContainerStart(context.Background(), resp.ID, types.ContainerStartOptions{}); err != nil {
    panic(err)
}

statusCh, errCh = cli.ContainerWait(context.Background(), resp.ID, container.WaitConditionNotRunning)

exitCh := make(chan bool)

go func(since string, exit chan bool) {

Loop:

    for {
        select {
        case <-exit:
            break Loop
        default:

            sinceReq := since
            time.Sleep(time.Second)
            since = strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
            out, err := cli.ContainerLogs(context.Background(), resp.ID, types.ContainerLogsOptions{Since: sinceReq, ShowStdout: true, ShowStderr: true})
            if err != nil {
                panic(err)
            }

            b, err := ioutil.ReadAll(out)
            if err != nil {
                panic(err)
            }
            log.Printf("Rolling log Contener \n%s", string(b))
            // Do something with the logs here...
        }
    }
}(nowUTC, exitCh)


select {
case err := <-errCh:
    exitCh <- true
    if err != nil {
        panic(err)
    }
case <-statusCh:
    exitCh <- true
}

Everything is fine except that ioutil.ReadAll(out) returns nothing.

I have tried to use several times or time formats like but still without any results:

What am I mising?

Upvotes: 1

Views: 400

Answers (1)

Guillaume Barr&#233;
Guillaume Barr&#233;

Reputation: 4218

Finally I got it working using the nowUTC :=time.Now().UTC(), but the issue was not only on the time format used.

The trick is that I was using "Docker Machine" on a laptop and I was closing my laptop every night. Whenever the laptop goes asleep the internal clock of the Docker Machine freeze.

When the laptop wakes up from sleep it results into a time drift between the laptop clock and Docker Machine's clock, and my Docker Machine was x hours late.

My Go code runs into an CLI app on my laptop and the time criteria of the request to extract the logs never matches the log content.

Everything works fine after a docker-machine restart

Upvotes: 2

Related Questions