diff --git a/driver/remote/driver.go b/driver/remote/driver.go index 56b1078d..eaf47e85 100644 --- a/driver/remote/driver.go +++ b/driver/remote/driver.go @@ -7,6 +7,7 @@ import ( "net" "os" "strings" + "sync" "time" "github.com/docker/buildx/driver" @@ -14,6 +15,7 @@ import ( "github.com/docker/buildx/util/progress" "github.com/moby/buildkit/client" "github.com/moby/buildkit/client/connhelper" + "github.com/moby/buildkit/util/tracing/delegated" "github.com/pkg/errors" ) @@ -25,6 +27,11 @@ type Driver struct { // https://github.com/docker/docs/blob/main/content/build/drivers/remote.md *tlsOpts defaultLoad bool + + // remote driver caches the client because its Bootstap/Info methods reuse it internally + clientOnce sync.Once + client *client.Client + err error } type tlsOpts struct { @@ -78,12 +85,18 @@ func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error { } func (d *Driver) Client(ctx context.Context, opts ...client.ClientOpt) (*client.Client, error) { - opts = append([]client.ClientOpt{ - client.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { - return d.Dial(ctx) - }), - }, opts...) - return client.New(ctx, "", opts...) + d.clientOnce.Do(func() { + opts = append([]client.ClientOpt{ + client.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { + return d.Dial(ctx) + }), + client.WithTracerDelegate(delegated.DefaultExporter), + }, opts...) + c, err := client.New(ctx, "", opts...) + d.client = c + d.err = err + }) + return d.client, d.err } func (d *Driver) Dial(ctx context.Context) (net.Conn, error) {