From ba02ff283e173613b691b3c0907fda89def440e7 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 13 Jun 2025 20:33:39 +0200 Subject: [PATCH] fix: Remove wrong buildkit version assignment (#747) * fix: Remove wrong buildkit version assignment * fix: buildkit session handling --- .../provider/resource_docker_image_funcs.go | 47 ++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/internal/provider/resource_docker_image_funcs.go b/internal/provider/resource_docker_image_funcs.go index dd32bd32..9ddbf3ed 100644 --- a/internal/provider/resource_docker_image_funcs.go +++ b/internal/provider/resource_docker_image_funcs.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "log" + "math/rand" "net" "os" "path/filepath" @@ -368,8 +369,8 @@ func buildDockerImage(ctx context.Context, rawBuild map[string]interface{}, imag buildContext := rawBuild["context"].(string) - buildKitSession := enableBuildKitIfSupported(ctx, client, &buildOptions) - + // Each build must have its own session. Never reuse buildKitSession! + buildKitSession, sessionDone := enableBuildKitIfSupported(ctx, client, &buildOptions) // If Buildkit is enabled, try to parse and use secrets if present. if buildKitSession != nil { if secretsRaw, secretsDefined := rawBuild["secrets"]; secretsDefined { @@ -387,14 +388,27 @@ func buildDockerImage(ctx context.Context, rawBuild map[string]interface{}, imag buildCtx, relDockerfile, err := prepareBuildContext(buildContext, buildOptions.Dockerfile) if err != nil { + if buildKitSession != nil { + log.Printf("[DEBUG] Closing BuildKit session (first error path): ID=%s", buildKitSession.ID()) + buildKitSession.Close() //nolint:errcheck + if sessionDone != nil { + <-sessionDone + } + } return err } buildOptions.Dockerfile = relDockerfile - buildOptions.Version = types.BuilderV1 var response types.ImageBuildResponse response, err = client.ImageBuild(ctx, buildCtx, buildOptions) if err != nil { + if buildKitSession != nil { + log.Printf("[DEBUG] Closing BuildKit session (second error path): ID=%s", buildKitSession.ID()) + buildKitSession.Close() //nolint:errcheck + if sessionDone != nil { + <-sessionDone + } + } return err } defer response.Body.Close() //nolint:errcheck @@ -403,6 +417,13 @@ func buildDockerImage(ctx context.Context, rawBuild map[string]interface{}, imag if err != nil { return fmt.Errorf("%s\n\n%s", err, buildResult) } + if buildKitSession != nil { + log.Printf("[DEBUG] Closing BuildKit session (success path): ID=%s", buildKitSession.ID()) + buildKitSession.Close() //nolint:errcheck + if sessionDone != nil { + <-sessionDone + } + } return nil } @@ -412,24 +433,28 @@ func enableBuildKitIfSupported( ctx context.Context, client *client.Client, buildOptions *types.ImageBuildOptions, -) *session.Session { +) (*session.Session, chan struct{}) { dockerClientVersion := client.ClientVersion() log.Printf("[DEBUG] DockerClientVersion: %v, minBuildKitDockerVersion: %v\n", dockerClientVersion, minBuildkitDockerVersion) if versions.GreaterThanOrEqualTo(dockerClientVersion, minBuildkitDockerVersion) { - log.Printf("[DEBUG] Enabling BuildKit") - s, _ := session.NewSession(ctx, "docker-provider") + // Generate a unique session key for each build + sessionKey := fmt.Sprintf("docker-provider-%d", rand.Int63()) + log.Printf("[DEBUG] Creating BuildKit session with key: %s", sessionKey) + s, _ := session.NewSession(ctx, sessionKey) dialSession := func(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) { return client.DialHijack(ctx, "/session", proto, meta) } - //nolint - go s.Run(ctx, dialSession) - defer s.Close() //nolint:errcheck + done := make(chan struct{}) + go func() { + s.Run(ctx, dialSession) //nolint:errcheck + close(done) + }() buildOptions.SessionID = s.ID() buildOptions.Version = types.BuilderBuildKit - return s + return s, done } else { buildOptions.Version = types.BuilderV1 - return nil + return nil, nil } }