Skip to content

Instantly share code, notes, and snippets.

@knight42
Created May 15, 2022 14:47
Show Gist options
  • Save knight42/6c128a2edf7cebcb6816343da833295a to your computer and use it in GitHub Desktop.
Save knight42/6c128a2edf7cebcb6816343da833295a to your computer and use it in GitHub Desktop.
Connect to the buildkitd embeded in dockerd
module q
go 1.18
replace github.com/docker/docker => github.com/docker/docker v20.10.3-0.20220224222438-c78f6963a1c0+incompatible
require (
github.com/containerd/console v1.0.3
github.com/docker/docker v20.10.7+incompatible
github.com/moby/buildkit v0.10.3
)
require (
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.5.1 // indirect
github.com/containerd/containerd v1.6.3-0.20220401172941-5ff8fce1fcc6 // indirect
github.com/containerd/continuity v0.2.3-0.20220330195504-d132b287edc8 // indirect
github.com/containerd/typeurl v1.0.2 // indirect
github.com/docker/cli v20.10.13+incompatible // indirect
github.com/docker/distribution v2.8.0+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/go-logr/logr v1.2.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gofrs/flock v0.7.3 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/moby/sys/signal v0.6.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/tonistiigi/fsutil v0.0.0-20220115021204-b19f7f9cb274 // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 // indirect
go.opentelemetry.io/otel v1.4.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 // indirect
go.opentelemetry.io/otel/sdk v1.4.1 // indirect
go.opentelemetry.io/otel/trace v1.4.1 // indirect
go.opentelemetry.io/proto/otlp v0.12.0 // indirect
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e // indirect
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
google.golang.org/grpc v1.45.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
)
package main
import (
"context"
"fmt"
"net"
"os"
"github.com/containerd/console"
dockerclient "github.com/docker/docker/client"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/util/progress/progresswriter"
)
func build() error {
ctx := context.Background()
dockerCli, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv, dockerclient.WithAPIVersionNegotiation())
if err != nil {
return fmt.Errorf("create docker client: %w", err)
}
_ = dockerCli
bkcli, err := client.New(ctx, "",
client.WithFailFast(),
// See also https://github.com/docker/buildx/blob/69824a5d2725205aca8155a8e38b5a10854dcf2b/driver/docker/driver.go#L48
client.WithContextDialer(func(context.Context, string) (net.Conn, error) {
return dockerCli.DialHijack(ctx, "/grpc", "h2c", nil)
}), client.WithSessionDialer(func(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) {
return dockerCli.DialHijack(ctx, "/session", proto, meta)
}),
)
if err != nil {
return fmt.Errorf("create buildkit client: %w", err)
}
state := llb.Image("alpine:edge").Run(llb.Shlex(`sh -c "echo 1 > /1.txt"`)).Root()
def, err := state.Marshal(ctx, llb.LinuxAmd64)
if err != nil {
return fmt.Errorf("marshal state: %w", err)
}
c, err := console.ConsoleFromFile(os.Stdout)
if err != nil {
return fmt.Errorf("create console: %w", err)
}
printer, err := progresswriter.NewPrinter(ctx, c, "auto")
if err != nil {
return fmt.Errorf("create progress writer: %w", err)
}
_, err = bkcli.Solve(ctx, def, client.SolveOpt{
Exports: []client.ExportEntry{
{
Type: "moby",
Attrs: map[string]string{
"name": "test:dev",
},
},
},
LocalDirs: map[string]string{
"context-dir": ".",
},
}, printer.Status())
if err != nil {
return fmt.Errorf("solve: %w", err)
}
<-printer.Done()
return printer.Err()
}
func main() {
err := build()
if err != nil {
panic(err)
}
}
@gaocegege
Copy link

		// See also https://github.com/docker/buildx/blob/69824a5d2725205aca8155a8e38b5a10854dcf2b/driver/docker/driver.go#L48
		client.WithContextDialer(func(context.Context, string) (net.Conn, error) {
			return dockerCli.DialHijack(ctx, "/grpc", "h2c", nil)
		}), client.WithSessionDialer(func(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) {
			return dockerCli.DialHijack(ctx, "/session", proto, meta)
		}),

Is it necessary for built-in load?

@gaocegege
Copy link

I followed the code here and got this error:

exporter "moby" could not be found

Not sure if it is related to the version.

@knight42
Copy link
Author

Is it necessary for built-in load?

It is necessary, but for connecting to the buildkitd bundled in dockerd. There is no extra image loading if we switch to the docker driver.

@knight42
Copy link
Author

exporter "moby" could not be found

That's a bit weird.. What's the output of docker version?

@gaocegege
Copy link

I resolved it. Thanks for the reply.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment