@@ -21,6 +21,7 @@ import (
21
21
"errors"
22
22
"fmt"
23
23
"os"
24
+ "os/exec"
24
25
"path/filepath"
25
26
"strings"
26
27
"sync"
@@ -45,6 +46,8 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars
45
46
}
46
47
}
47
48
49
+ recreate := uo .recreateStrategy ()
50
+
48
51
var (
49
52
containers = make (map [string ]serviceparser.Container ) // key: container ID
50
53
services = []string {}
@@ -57,7 +60,7 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars
57
60
for _ , container := range ps .Containers {
58
61
container := container
59
62
runEG .Go (func () error {
60
- id , err := c .upServiceContainer (ctx , ps , container )
63
+ id , err := c .upServiceContainer (ctx , ps , container , recreate )
61
64
if err != nil {
62
65
return err
63
66
}
@@ -87,6 +90,7 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars
87
90
Follow : true ,
88
91
NoColor : uo .NoColor ,
89
92
NoLogPrefix : uo .NoLogPrefix ,
93
+ LatestRun : recreate == RecreateNever ,
90
94
}
91
95
if err := c .Logs (ctx , lo , services ); err != nil {
92
96
return err
@@ -118,15 +122,35 @@ func (c *Composer) ensureServiceImage(ctx context.Context, ps *serviceparser.Ser
118
122
119
123
// upServiceContainer must be called after ensureServiceImage
120
124
// 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 ) {
122
126
// 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 )
124
128
if err != nil {
125
129
return "" , fmt .Errorf ("error while checking for containers with name %q: %s" , container .Name , err )
126
130
}
127
131
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
+
128
152
// delete container if it already exists
129
- if exists {
153
+ if existingCid != "" {
130
154
log .G (ctx ).Debugf ("Container %q already exists, deleting" , container .Name )
131
155
delCmd := c .createNerdctlCmd (ctx , "rm" , "-f" , container .Name )
132
156
if err = delCmd .Run (); err != nil {
@@ -151,12 +175,6 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse
151
175
defer os .RemoveAll (tempDir )
152
176
cidFilename := filepath .Join (tempDir , "cid" )
153
177
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
-
160
178
//add metadata labels to container https://github.com/compose-spec/compose-spec/blob/master/spec.md#labels
161
179
container .RunArgs = append ([]string {
162
180
"--cidfile=" + cidFilename ,
@@ -169,12 +187,24 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse
169
187
log .G (ctx ).Debugf ("Running %v" , cmd .Args )
170
188
}
171
189
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 )
175
205
}
176
206
177
- if service . Unparsed . StdinOpen {
207
+ if stdinOpen {
178
208
cmd .Stdin = os .Stdin
179
209
}
180
210
if ! runFlagD {
@@ -183,14 +213,9 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse
183
213
// Always propagate stderr to print detailed error messages (https://github.com/containerd/nerdctl/issues/1942)
184
214
cmd .Stderr = os .Stderr
185
215
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 )
189
218
}
190
219
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
196
221
}
0 commit comments