@@ -45,9 +45,6 @@ import (
4545)
4646
4747const (
48- extLifecycle = "x-lifecycle"
49- forceRecreate = "force_recreate"
50-
5148 doubledContainerNameWarning = "WARNING: The %q service is using the custom container name %q. " +
5249 "Docker requires each container to have a unique name. " +
5350 "Remove the custom name to scale the service.\n "
@@ -108,9 +105,7 @@ func (c *convergence) apply(ctx context.Context, project *types.Project, options
108105 })
109106}
110107
111- var mu sync.Mutex
112-
113- func (c * convergence ) ensureService (ctx context.Context , project * types.Project , service types.ServiceConfig , recreate string , inherit bool , timeout * time.Duration ) error {
108+ func (c * convergence ) ensureService (ctx context.Context , project * types.Project , service types.ServiceConfig , recreate string , inherit bool , timeout * time.Duration ) error { //nolint:gocyclo
114109 expected , err := getScale (service )
115110 if err != nil {
116111 return err
@@ -147,6 +142,7 @@ func (c *convergence) ensureService(ctx context.Context, project *types.Project,
147142 // If we don't get a container number (?) just sort by creation date
148143 return containers [i ].Created < containers [j ].Created
149144 })
145+
150146 for i , container := range containers {
151147 if i >= expected {
152148 // Scale Down
@@ -163,6 +159,11 @@ func (c *convergence) ensureService(ctx context.Context, project *types.Project,
163159 return err
164160 }
165161 if mustRecreate {
162+ err := c .stopDependentContainers (ctx , project , service )
163+ if err != nil {
164+ return err
165+ }
166+
166167 i , container := i , container
167168 eg .Go (tracing .SpanWrapFuncForErrGroup (ctx , "container/recreate" , tracing .ContainerOptions (container ), func (ctx context.Context ) error {
168169 recreated , err := c .service .recreateContainer (ctx , project , service , container , inherit , timeout )
@@ -172,8 +173,8 @@ func (c *convergence) ensureService(ctx context.Context, project *types.Project,
172173 continue
173174 }
174175
175- // Enforce non-diverged containers are running
176176 w := progress .ContextWriter (ctx )
177+ // Enforce non-diverged containers are running
177178 name := getContainerProgressName (container )
178179 switch container .State {
179180 case ContainerRunning :
@@ -217,6 +218,25 @@ func (c *convergence) ensureService(ctx context.Context, project *types.Project,
217218 return err
218219}
219220
221+ func (c * convergence ) stopDependentContainers (ctx context.Context , project * types.Project , service types.ServiceConfig ) error {
222+ w := progress .ContextWriter (ctx )
223+ // Stop dependent containers, so they will be restarted after service is re-created
224+ dependents := project .GetDependentsForService (service )
225+ for _ , name := range dependents {
226+ dependents := c .observedState [name ]
227+ err := c .service .stopContainers (ctx , w , dependents , nil )
228+ if err != nil {
229+ return err
230+ }
231+ for i , dependent := range dependents {
232+ dependent .State = ContainerExited
233+ dependents [i ] = dependent
234+ }
235+ c .observedState [name ] = dependents
236+ }
237+ return nil
238+ }
239+
220240func getScale (config types.ServiceConfig ) (int , error ) {
221241 scale := config .GetScale ()
222242 if scale > 1 && config .ContainerName != "" {
@@ -296,7 +316,7 @@ func mustRecreate(expected types.ServiceConfig, actual moby.Container, policy st
296316 if policy == api .RecreateNever {
297317 return false , nil
298318 }
299- if policy == api .RecreateForce || expected . Extensions [ extLifecycle ] == forceRecreate {
319+ if policy == api .RecreateForce {
300320 return true , nil
301321 }
302322 configHash , err := ServiceHash (expected )
@@ -535,26 +555,9 @@ func (s *composeService) recreateContainer(ctx context.Context, project *types.P
535555 }
536556
537557 w .Event (progress .NewEvent (getContainerProgressName (replaced ), progress .Done , "Recreated" ))
538- setDependentLifecycle (project , service .Name , forceRecreate )
539558 return created , err
540559}
541560
542- // setDependentLifecycle define the Lifecycle strategy for all services to depend on specified service
543- func setDependentLifecycle (project * types.Project , service string , strategy string ) {
544- mu .Lock ()
545- defer mu .Unlock ()
546-
547- for i , s := range project .Services {
548- if utils .StringContains (s .GetDependencies (), service ) {
549- if s .Extensions == nil {
550- s .Extensions = map [string ]interface {}{}
551- }
552- s .Extensions [extLifecycle ] = strategy
553- project .Services [i ] = s
554- }
555- }
556- }
557-
558561func (s * composeService ) startContainer (ctx context.Context , container moby.Container ) error {
559562 w := progress .ContextWriter (ctx )
560563 w .Event (progress .NewEvent (getContainerProgressName (container ), progress .Working , "Restart" ))
0 commit comments