@@ -21,6 +21,7 @@ import (
2121 "errors"
2222 "fmt"
2323 "os"
24+ "os/exec"
2425 "path/filepath"
2526 "strings"
2627 "sync"
@@ -45,6 +46,8 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars
4546 }
4647 }
4748
49+ recreate := uo .recreateStrategy ()
50+
4851 var (
4952 containers = make (map [string ]serviceparser.Container ) // key: container ID
5053 services = []string {}
@@ -57,7 +60,7 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars
5760 for _ , container := range ps .Containers {
5861 container := container
5962 runEG .Go (func () error {
60- id , err := c .upServiceContainer (ctx , ps , container )
63+ id , err := c .upServiceContainer (ctx , ps , container , recreate )
6164 if err != nil {
6265 return err
6366 }
@@ -87,6 +90,7 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars
8790 Follow : true ,
8891 NoColor : uo .NoColor ,
8992 NoLogPrefix : uo .NoLogPrefix ,
93+ LatestRun : recreate == RecreateNever ,
9094 }
9195 if err := c .Logs (ctx , lo , services ); err != nil {
9296 return err
@@ -118,15 +122,35 @@ func (c *Composer) ensureServiceImage(ctx context.Context, ps *serviceparser.Ser
118122
119123// upServiceContainer must be called after ensureServiceImage
120124// upServiceContainer returns container ID
121- func (c * Composer ) upServiceContainer (ctx context.Context , service * serviceparser.Service , container serviceparser.Container ) (string , error ) {
125+ func (c * Composer ) upServiceContainer (ctx context.Context , service * serviceparser.Service , container serviceparser.Container , recreate string ) (string , error ) {
122126 // check if container already exists
123- exists , err := c .containerExists (ctx , container .Name , service .Unparsed .Name )
127+ existingCid , err := c .containerID (ctx , container .Name , service .Unparsed .Name )
124128 if err != nil {
125129 return "" , fmt .Errorf ("error while checking for containers with name %q: %s" , container .Name , err )
126130 }
127131
132+ // FIXME
133+ if service .Unparsed .StdinOpen != service .Unparsed .Tty {
134+ return "" , fmt .Errorf ("currently StdinOpen(-i) and Tty(-t) should be same" )
135+ }
136+
137+ var runFlagD bool
138+ if ! service .Unparsed .StdinOpen && ! service .Unparsed .Tty {
139+ container .RunArgs = append ([]string {"-d" }, container .RunArgs ... )
140+ runFlagD = true
141+ }
142+
143+ // start the existing container and exit early
144+ if existingCid != "" && recreate == RecreateNever {
145+ cmd := c .createNerdctlCmd (ctx , append ([]string {"start" }, existingCid )... )
146+ if err := c .executeUpCmd (ctx , cmd , container .Name , runFlagD , service .Unparsed .StdinOpen ); err != nil {
147+ return "" , fmt .Errorf ("error while starting existing container %s: %w" , container .Name , err )
148+ }
149+ return existingCid , nil
150+ }
151+
128152 // delete container if it already exists
129- if exists {
153+ if existingCid != "" {
130154 log .G (ctx ).Debugf ("Container %q already exists, deleting" , container .Name )
131155 delCmd := c .createNerdctlCmd (ctx , "rm" , "-f" , container .Name )
132156 if err = delCmd .Run (); err != nil {
@@ -151,12 +175,6 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse
151175 defer os .RemoveAll (tempDir )
152176 cidFilename := filepath .Join (tempDir , "cid" )
153177
154- var runFlagD bool
155- if ! service .Unparsed .StdinOpen && ! service .Unparsed .Tty {
156- container .RunArgs = append ([]string {"-d" }, container .RunArgs ... )
157- runFlagD = true
158- }
159-
160178 //add metadata labels to container https://github.com/compose-spec/compose-spec/blob/master/spec.md#labels
161179 container .RunArgs = append ([]string {
162180 "--cidfile=" + cidFilename ,
@@ -169,12 +187,24 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse
169187 log .G (ctx ).Debugf ("Running %v" , cmd .Args )
170188 }
171189
172- // FIXME
173- if service .Unparsed .StdinOpen != service .Unparsed .Tty {
174- return "" , fmt .Errorf ("currently StdinOpen(-i) and Tty(-t) should be same" )
190+ if err := c .executeUpCmd (ctx , cmd , container .Name , runFlagD , service .Unparsed .StdinOpen ); err != nil {
191+ return "" , fmt .Errorf ("error while creating container %s: %w" , container .Name , err )
192+ }
193+
194+ cid , err := os .ReadFile (cidFilename )
195+ if err != nil {
196+ return "" , fmt .Errorf ("error while creating container %s: %w" , container .Name , err )
197+ }
198+ return strings .TrimSpace (string (cid )), nil
199+ }
200+
201+ func (c * Composer ) executeUpCmd (ctx context.Context , cmd * exec.Cmd , containerName string , runFlagD , stdinOpen bool ) error {
202+ log .G (ctx ).Infof ("Running %v" , cmd .Args )
203+ if c .DebugPrintFull {
204+ log .G (ctx ).Debugf ("Running %v" , cmd .Args )
175205 }
176206
177- if service . Unparsed . StdinOpen {
207+ if stdinOpen {
178208 cmd .Stdin = os .Stdin
179209 }
180210 if ! runFlagD {
@@ -183,14 +213,9 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse
183213 // Always propagate stderr to print detailed error messages (https://github.com/containerd/nerdctl/issues/1942)
184214 cmd .Stderr = os .Stderr
185215
186- err = cmd .Run ()
187- if err != nil {
188- return "" , fmt .Errorf ("error while creating container %s: %w" , container .Name , err )
216+ if err := cmd .Run (); err != nil {
217+ return fmt .Errorf ("error while creating container %s: %w" , containerName , err )
189218 }
190219
191- cid , err := os .ReadFile (cidFilename )
192- if err != nil {
193- return "" , fmt .Errorf ("error while creating container %s: %w" , container .Name , err )
194- }
195- return strings .TrimSpace (string (cid )), nil
220+ return nil
196221}
0 commit comments