Merge pull request #332 from tonistiigi/bootstrap-logs

docker-container: show logs on bootstrap error
pull/351/head
Tõnis Tiigi 5 years ago committed by GitHub
commit e24e04be57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -44,7 +44,7 @@ func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
if err := d.start(ctx, sub); err != nil { if err := d.start(ctx, sub); err != nil {
return err return err
} }
if err := d.wait(ctx); err != nil { if err := d.wait(ctx, sub); err != nil {
return err return err
} }
return nil return nil
@ -106,7 +106,7 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error {
if err := d.start(ctx, l); err != nil { if err := d.start(ctx, l); err != nil {
return err return err
} }
if err := d.wait(ctx); err != nil { if err := d.wait(ctx, l); err != nil {
return err return err
} }
return nil return nil
@ -116,17 +116,28 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error {
return nil return nil
} }
func (d *Driver) wait(ctx context.Context) error { func (d *Driver) wait(ctx context.Context, l progress.SubLogger) error {
try := 0 try := 1
for { for {
if err := d.run(ctx, []string{"buildctl", "debug", "workers"}); err != nil { bufStdout := &bytes.Buffer{}
if try > 10 { bufStderr := &bytes.Buffer{}
if err := d.run(ctx, []string{"buildctl", "debug", "workers"}, bufStdout, bufStderr); err != nil {
if try > 15 {
if err != nil {
d.copyLogs(context.TODO(), l)
if bufStdout.Len() != 0 {
l.Log(1, bufStdout.Bytes())
}
if bufStderr.Len() != 0 {
l.Log(2, bufStderr.Bytes())
}
}
return err return err
} }
select { select {
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return ctx.Err()
case <-time.After(time.Duration(100+try*20) * time.Millisecond): case <-time.After(time.Duration(try*120) * time.Millisecond):
try++ try++
continue continue
} }
@ -135,6 +146,21 @@ func (d *Driver) wait(ctx context.Context) error {
} }
} }
func (d *Driver) copyLogs(ctx context.Context, l progress.SubLogger) error {
rc, err := d.DockerAPI.ContainerLogs(ctx, d.Name, types.ContainerLogsOptions{
ShowStdout: true, ShowStderr: true,
})
if err != nil {
return err
}
stdout := &logWriter{logger: l, stream: 1}
stderr := &logWriter{logger: l, stream: 2}
if _, err := stdcopy.StdCopy(stdout, stderr, rc); err != nil {
return err
}
return rc.Close()
}
func (d *Driver) exec(ctx context.Context, cmd []string) (string, net.Conn, error) { func (d *Driver) exec(ctx context.Context, cmd []string) (string, net.Conn, error) {
execConfig := types.ExecConfig{ execConfig := types.ExecConfig{
Cmd: cmd, Cmd: cmd,
@ -159,12 +185,12 @@ func (d *Driver) exec(ctx context.Context, cmd []string) (string, net.Conn, erro
return execID, resp.Conn, nil return execID, resp.Conn, nil
} }
func (d *Driver) run(ctx context.Context, cmd []string) error { func (d *Driver) run(ctx context.Context, cmd []string, stdout, stderr io.Writer) (err error) {
id, conn, err := d.exec(ctx, cmd) id, conn, err := d.exec(ctx, cmd)
if err != nil { if err != nil {
return err return err
} }
if _, err := io.Copy(ioutil.Discard, conn); err != nil { if _, err := stdcopy.StdCopy(stdout, stderr, conn); err != nil {
return err return err
} }
conn.Close() conn.Close()
@ -259,7 +285,7 @@ func (d *Driver) Features() map[driver.Feature]bool {
func demuxConn(c net.Conn) net.Conn { func demuxConn(c net.Conn) net.Conn {
pr, pw := io.Pipe() pr, pw := io.Pipe()
// TODO: rewrite parser with Reader() to avoid goroutine switch // TODO: rewrite parser with Reader() to avoid goroutine switch
go stdcopy.StdCopy(pw, os.Stdout, c) go stdcopy.StdCopy(pw, os.Stderr, c)
return &demux{ return &demux{
Conn: c, Conn: c,
Reader: pr, Reader: pr,
@ -297,3 +323,13 @@ func readFileToTar(fn string) (*bytes.Buffer, error) {
} }
return buf, nil return buf, nil
} }
type logWriter struct {
logger progress.SubLogger
stream int
}
func (l *logWriter) Write(dt []byte) (int, error) {
l.logger.Log(l.stream, dt)
return len(dt), nil
}

Loading…
Cancel
Save