88 "fmt"
99 "io"
1010 "log"
11+ "math/rand"
1112 "net"
1213 "os"
1314 "path/filepath"
@@ -368,8 +369,8 @@ func buildDockerImage(ctx context.Context, rawBuild map[string]interface{}, imag
368369
369370 buildContext := rawBuild ["context" ].(string )
370371
371- buildKitSession := enableBuildKitIfSupported ( ctx , client , & buildOptions )
372-
372+ // Each build must have its own session. Never reuse buildKitSession!
373+ buildKitSession , sessionDone := enableBuildKitIfSupported ( ctx , client , & buildOptions )
373374 // If Buildkit is enabled, try to parse and use secrets if present.
374375 if buildKitSession != nil {
375376 if secretsRaw , secretsDefined := rawBuild ["secrets" ]; secretsDefined {
@@ -387,14 +388,27 @@ func buildDockerImage(ctx context.Context, rawBuild map[string]interface{}, imag
387388
388389 buildCtx , relDockerfile , err := prepareBuildContext (buildContext , buildOptions .Dockerfile )
389390 if err != nil {
391+ if buildKitSession != nil {
392+ log .Printf ("[DEBUG] Closing BuildKit session (first error path): ID=%s" , buildKitSession .ID ())
393+ buildKitSession .Close () //nolint:errcheck
394+ if sessionDone != nil {
395+ <- sessionDone
396+ }
397+ }
390398 return err
391399 }
392400 buildOptions .Dockerfile = relDockerfile
393- buildOptions .Version = types .BuilderV1
394401
395402 var response types.ImageBuildResponse
396403 response , err = client .ImageBuild (ctx , buildCtx , buildOptions )
397404 if err != nil {
405+ if buildKitSession != nil {
406+ log .Printf ("[DEBUG] Closing BuildKit session (second error path): ID=%s" , buildKitSession .ID ())
407+ buildKitSession .Close () //nolint:errcheck
408+ if sessionDone != nil {
409+ <- sessionDone
410+ }
411+ }
398412 return err
399413 }
400414 defer response .Body .Close () //nolint:errcheck
@@ -403,6 +417,13 @@ func buildDockerImage(ctx context.Context, rawBuild map[string]interface{}, imag
403417 if err != nil {
404418 return fmt .Errorf ("%s\n \n %s" , err , buildResult )
405419 }
420+ if buildKitSession != nil {
421+ log .Printf ("[DEBUG] Closing BuildKit session (success path): ID=%s" , buildKitSession .ID ())
422+ buildKitSession .Close () //nolint:errcheck
423+ if sessionDone != nil {
424+ <- sessionDone
425+ }
426+ }
406427 return nil
407428}
408429
@@ -412,24 +433,28 @@ func enableBuildKitIfSupported(
412433 ctx context.Context ,
413434 client * client.Client ,
414435 buildOptions * types.ImageBuildOptions ,
415- ) * session.Session {
436+ ) ( * session.Session , chan struct {}) {
416437 dockerClientVersion := client .ClientVersion ()
417438 log .Printf ("[DEBUG] DockerClientVersion: %v, minBuildKitDockerVersion: %v\n " , dockerClientVersion , minBuildkitDockerVersion )
418439 if versions .GreaterThanOrEqualTo (dockerClientVersion , minBuildkitDockerVersion ) {
419- log .Printf ("[DEBUG] Enabling BuildKit" )
420- s , _ := session .NewSession (ctx , "docker-provider" )
440+ // Generate a unique session key for each build
441+ sessionKey := fmt .Sprintf ("docker-provider-%d" , rand .Int63 ())
442+ log .Printf ("[DEBUG] Creating BuildKit session with key: %s" , sessionKey )
443+ s , _ := session .NewSession (ctx , sessionKey )
421444 dialSession := func (ctx context.Context , proto string , meta map [string ][]string ) (net.Conn , error ) {
422445 return client .DialHijack (ctx , "/session" , proto , meta )
423446 }
424- //nolint
425- go s .Run (ctx , dialSession )
426- defer s .Close () //nolint:errcheck
447+ done := make (chan struct {})
448+ go func () {
449+ s .Run (ctx , dialSession ) //nolint:errcheck
450+ close (done )
451+ }()
427452 buildOptions .SessionID = s .ID ()
428453 buildOptions .Version = types .BuilderBuildKit
429- return s
454+ return s , done
430455 } else {
431456 buildOptions .Version = types .BuilderV1
432- return nil
457+ return nil , nil
433458 }
434459}
435460
0 commit comments