@@ -3,110 +3,68 @@ package build
33import (
44 "context"
55 _ "crypto/sha256" // ensure digests can be computed
6- "encoding/json"
7- "fmt"
86 "io"
97 "sync"
108 "sync/atomic"
119 "syscall"
1210
1311 controllerapi "github.com/docker/buildx/controller/pb"
14- "github.com/moby/buildkit/client"
15- "github.com/moby/buildkit/exporter/containerimage/exptypes"
1612 gateway "github.com/moby/buildkit/frontend/gateway/client"
17- "github.com/moby/buildkit/solver/pb"
18- specs "github.com/opencontainers/image-spec/specs-go/v1"
1913 "github.com/pkg/errors"
2014 "github.com/sirupsen/logrus"
2115)
2216
23- // ResultContext is a build result with the client that built it.
24- type ResultContext struct {
25- Client * client.Client
26- Res * gateway.Result
27- }
28-
2917type Container struct {
3018 cancelOnce sync.Once
3119 containerCancel func ()
32-
33- isUnavailable atomic.Bool
34-
35- initStarted atomic.Bool
36-
37- container gateway.Container
38- image * specs.Image
39-
40- releaseCh chan struct {}
20+ isUnavailable atomic.Bool
21+ initStarted atomic.Bool
22+ container gateway.Container
23+ releaseCh chan struct {}
24+ resultCtx * ResultContext
4125}
4226
43- func NewContainer (ctx context.Context , resultCtx * ResultContext ) (* Container , error ) {
44- c , res := resultCtx .Client , resultCtx .Res
45-
27+ func NewContainer (ctx context.Context , resultCtx * ResultContext , cfg * controllerapi.InvokeConfig ) (* Container , error ) {
4628 mainCtx := ctx
4729
4830 ctrCh := make (chan * Container )
4931 errCh := make (chan error )
5032 go func () {
51- _ , err := c . Build ( context . TODO (), client. SolveOpt {}, "buildx" , func (ctx context.Context , c gateway.Client ) (* gateway.Result , error ) {
33+ err := resultCtx . build ( func (ctx context.Context , c gateway.Client ) (* gateway.Result , error ) {
5234 ctx , cancel := context .WithCancel (ctx )
5335 go func () {
5436 <- mainCtx .Done ()
5537 cancel ()
5638 }()
5739
58- if res .Ref == nil {
59- return nil , errors .Errorf ("no reference is registered" )
60- }
61- st , err := res .Ref .ToState ()
62- if err != nil {
63- return nil , err
64- }
65- def , err := st .Marshal (ctx )
66- if err != nil {
67- return nil , err
68- }
69- imgRef , err := c .Solve (ctx , gateway.SolveRequest {
70- Definition : def .ToPB (),
71- })
40+ containerCfg , err := resultCtx .getContainerConfig (ctx , c , cfg )
7241 if err != nil {
7342 return nil , err
7443 }
7544 containerCtx , containerCancel := context .WithCancel (ctx )
7645 defer containerCancel ()
77- bkContainer , err := c .NewContainer (containerCtx , gateway.NewContainerRequest {
78- Mounts : []gateway.Mount {
79- {
80- Dest : "/" ,
81- MountType : pb .MountType_BIND ,
82- Ref : imgRef .Ref ,
83- },
84- },
85- })
46+ bkContainer , err := c .NewContainer (containerCtx , containerCfg )
8647 if err != nil {
8748 return nil , err
8849 }
89- imgData := res .Metadata [exptypes .ExporterImageConfigKey ]
90- var img * specs.Image
91- if len (imgData ) > 0 {
92- img = & specs.Image {}
93- if err := json .Unmarshal (imgData , img ); err != nil {
94- fmt .Println (err )
95- return nil , err
96- }
97- }
9850 releaseCh := make (chan struct {})
9951 container := & Container {
10052 containerCancel : containerCancel ,
10153 container : bkContainer ,
102- image : img ,
10354 releaseCh : releaseCh ,
55+ resultCtx : resultCtx ,
10456 }
57+ doneCh := make (chan struct {})
58+ defer close (doneCh )
59+ resultCtx .registerCleanup (func () {
60+ container .Cancel ()
61+ <- doneCh
62+ })
10563 ctrCh <- container
10664 <- container .releaseCh
10765
10866 return nil , bkContainer .Release (ctx )
109- }, nil )
67+ })
11068 if err != nil {
11169 errCh <- err
11270 }
@@ -146,56 +104,20 @@ func (c *Container) Exec(ctx context.Context, cfg *controllerapi.InvokeConfig, s
146104 c .markUnavailable ()
147105 }()
148106 }
149- err := exec (ctx , cfg , c . container , c . image , stdin , stdout , stderr )
107+ err := exec (ctx , c . resultCtx , cfg , c . container , stdin , stdout , stderr )
150108 if err != nil {
151109 // Container becomes unavailable if one of the processes fails in it.
152110 c .markUnavailable ()
153111 }
154112 return err
155113}
156114
157- func exec (ctx context.Context , cfg * controllerapi.InvokeConfig , ctr gateway.Container , img * specs.Image , stdin io.ReadCloser , stdout io.WriteCloser , stderr io.WriteCloser ) error {
158- user := ""
159- if ! cfg .NoUser {
160- user = cfg .User
161- } else if img != nil {
162- user = img .Config .User
163- }
164-
165- cwd := ""
166- if ! cfg .NoCwd {
167- cwd = cfg .Cwd
168- } else if img != nil {
169- cwd = img .Config .WorkingDir
170- }
171-
172- env := []string {}
173- if img != nil {
174- env = append (env , img .Config .Env ... )
175- }
176- env = append (env , cfg .Env ... )
177-
178- args := []string {}
179- if cfg .Entrypoint != nil {
180- args = append (args , cfg .Entrypoint ... )
181- }
182- if cfg .Cmd != nil {
183- args = append (args , cfg .Cmd ... )
184- }
185- // caller should always set args
186- if len (args ) == 0 {
187- return errors .Errorf ("specify args to execute" )
115+ func exec (ctx context.Context , resultCtx * ResultContext , cfg * controllerapi.InvokeConfig , ctr gateway.Container , stdin io.ReadCloser , stdout io.WriteCloser , stderr io.WriteCloser ) error {
116+ processCfg , err := resultCtx .getProcessConfig (cfg , stdin , stdout , stderr )
117+ if err != nil {
118+ return err
188119 }
189- proc , err := ctr .Start (ctx , gateway.StartRequest {
190- Args : args ,
191- Env : env ,
192- User : user ,
193- Cwd : cwd ,
194- Tty : cfg .Tty ,
195- Stdin : stdin ,
196- Stdout : stdout ,
197- Stderr : stderr ,
198- })
120+ proc , err := ctr .Start (ctx , processCfg )
199121 if err != nil {
200122 return errors .Errorf ("failed to start container: %v" , err )
201123 }
0 commit comments