Skip to content

Service and Container correlation is broken #122

Description

@pvande

Describe the bug
When multiple projects use the same service names, it's possible – and potentially common – for the listed services to refer to another project's containers.

To Reproduce
Steps to reproduce the behavior:

  1. Create two separate docker-compose.yml files in two different directories.
  2. Add both an app service and a project-specific service to each docker-compose.yml file.
  3. Build and run both project's containers.
  4. Run lazydocker in both projects.

Expected behaviour
Each instance of lazydocker shows two services, and both services refer to different containers.

Observed behavior
lazydocker matches the Service record against the first Container with a matching service name label. This can be easily validated by examining the com.docker.compose.project label in the "Container Config" panel for the listed services.

This bug has a few knock-on effects:

  • The Containers panel only shows containers that have a service name that does not match a Service in the current project. If (e.g.) the app Service has captured the container for the wrong project, the container for the correct app Service is also inaccessible.
  • Since the docker-compose project name cannot be reliably determined externally (without introducing a new convention), lazydocker currently relies on the appropriate label of the first Service's container to determine the project name (falling back to $PWD). If that Service has captured the container for the wrong project, the displayed project name will also be incorrect.

Desktop (please complete the following information):

  • OS: macOS 10.14.5
  • Lazydocker v0.5.5

Additional context

The Service and Container matching behavior described is supported by a reading of the current logic here:

func (c *DockerCommand) assignContainersToServices(containers []*Container, services []*Service) {
L:
for _, service := range services {
for _, container := range containers {
if !container.OneOff && container.ServiceName == service.Name {
service.Container = container
continue L
}
}
service.Container = nil
}
}
// filterOutExited filters out the exited containers if c.ShowExited is false
func (c *DockerCommand) filterOutExited(containers []*Container) []*Container {
if c.ShowExited {
return containers
}
toReturn := []*Container{}
for _, container := range containers {
if container.Container.State != "exited" {
toReturn = append(toReturn, container)
}
}
return toReturn
}
// obtainStandaloneContainers returns standalone containers. Standalone containers are containers which are either one-off containers, or whose service is not part of this docker-compose context
func (c *DockerCommand) obtainStandaloneContainers(containers []*Container, services []*Service) []*Container {
standaloneContainers := []*Container{}
L:
for _, container := range containers {
for _, service := range services {
if !container.OneOff && container.ServiceName != "" && container.ServiceName == service.Name {
continue L
}
}
standaloneContainers = append(standaloneContainers, container)
}
return standaloneContainers
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions