Fix concurrent map read/write when recreating containers

Signed-off-by: Luis Rascao <luis.rascao@gmail.com>
This commit is contained in:
Luis Rascao 2023-03-17 09:49:39 +00:00 committed by Nicolas De loof
parent 9ec43973e2
commit bfeb1dc277
2 changed files with 37 additions and 18 deletions

View File

@ -399,7 +399,8 @@ func (s *composeService) createContainer(ctx context.Context, project *types.Pro
w := progress.ContextWriter(ctx) w := progress.ContextWriter(ctx)
eventName := "Container " + name eventName := "Container " + name
w.Event(progress.CreatingEvent(eventName)) w.Event(progress.CreatingEvent(eventName))
container, err = s.createMobyContainer(ctx, project, service, name, number, nil, autoRemove, useNetworkAliases, attachStdin, w) container, err = s.createMobyContainer(ctx, project, service, name, number, nil,
autoRemove, useNetworkAliases, attachStdin, w, mergeLabels(service.Labels, service.CustomLabels))
if err != nil { if err != nil {
return return
} }
@ -424,8 +425,9 @@ func (s *composeService) recreateContainer(ctx context.Context, project *types.P
} }
name := getContainerName(project.Name, service, number) name := getContainerName(project.Name, service, number)
tmpName := fmt.Sprintf("%s_%s", replaced.ID[:12], name) tmpName := fmt.Sprintf("%s_%s", replaced.ID[:12], name)
service.CustomLabels[api.ContainerReplaceLabel] = replaced.ID created, err = s.createMobyContainer(ctx, project, service, tmpName, number, inherited,
created, err = s.createMobyContainer(ctx, project, service, tmpName, number, inherited, false, true, false, w) false, true, false, w,
mergeLabels(service.Labels, service.CustomLabels).Add(api.ContainerReplaceLabel, replaced.ID))
if err != nil { if err != nil {
return created, err return created, err
} }
@ -475,10 +477,19 @@ func (s *composeService) startContainer(ctx context.Context, container moby.Cont
return nil return nil
} }
func (s *composeService) createMobyContainer(ctx context.Context, project *types.Project, service types.ServiceConfig, func (s *composeService) createMobyContainer(ctx context.Context,
name string, number int, inherit *moby.Container, autoRemove bool, useNetworkAliases bool, attachStdin bool, w progress.Writer) (moby.Container, error) { project *types.Project,
service types.ServiceConfig,
name string,
number int,
inherit *moby.Container,
autoRemove, useNetworkAliases, attachStdin bool,
w progress.Writer,
labels types.Labels,
) (moby.Container, error) {
var created moby.Container var created moby.Container
containerConfig, hostConfig, networkingConfig, err := s.getCreateOptions(ctx, project, service, number, inherit, autoRemove, attachStdin) containerConfig, hostConfig, networkingConfig, err := s.getCreateOptions(ctx, project, service, number, inherit,
autoRemove, attachStdin, labels)
if err != nil { if err != nil {
return created, err return created, err
} }
@ -725,3 +736,13 @@ func (s *composeService) startService(ctx context.Context, project *types.Projec
} }
return nil return nil
} }
func mergeLabels(ls ...types.Labels) types.Labels {
merged := types.Labels{}
for _, l := range ls {
for k, v := range l {
merged[k] = v
}
}
return merged
}

View File

@ -236,10 +236,16 @@ func (s *composeService) ensureProjectVolumes(ctx context.Context, project *type
return nil return nil
} }
func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project, service types.ServiceConfig, func (s *composeService) getCreateOptions(ctx context.Context,
number int, inherit *moby.Container, autoRemove bool, attachStdin bool) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) { p *types.Project,
service types.ServiceConfig,
number int,
inherit *moby.Container,
autoRemove, attachStdin bool,
labels types.Labels,
) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) {
labels, err := s.prepareLabels(service, number) labels, err := s.prepareLabels(labels, service, number)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
@ -451,15 +457,7 @@ func parseSecurityOpts(p *types.Project, securityOpts []string) ([]string, bool,
return parsed, unconfined, nil return parsed, unconfined, nil
} }
func (s *composeService) prepareLabels(service types.ServiceConfig, number int) (map[string]string, error) { func (s *composeService) prepareLabels(labels types.Labels, service types.ServiceConfig, number int) (map[string]string, error) {
labels := map[string]string{}
for k, v := range service.Labels {
labels[k] = v
}
for k, v := range service.CustomLabels {
labels[k] = v
}
hash, err := ServiceHash(service) hash, err := ServiceHash(service)
if err != nil { if err != nil {
return nil, err return nil, err