diff --git a/cmd/compose/down.go b/cmd/compose/down.go index d3080ed2df..0cffb97a25 100644 --- a/cmd/compose/down.go +++ b/cmd/compose/down.go @@ -88,7 +88,7 @@ func runDown(ctx context.Context, dockerCli command.Cli, backend api.Service, op timeoutValue := time.Duration(opts.timeout) * time.Second timeout = &timeoutValue } - return backend.Down(ctx, name, api.DownOptions{ + err = backend.Down(ctx, name, api.DownOptions{ RemoveOrphans: opts.removeOrphans, Project: project, Timeout: timeout, @@ -96,4 +96,12 @@ func runDown(ctx context.Context, dockerCli command.Cli, backend api.Service, op Volumes: opts.volumes, Services: services, }) + if err != nil { + return err + } + err = killProcessesUsingExposedPorts(project) + if err != nil { + return err + } + return nil } diff --git a/cmd/compose/port_cleanup.go b/cmd/compose/port_cleanup.go new file mode 100644 index 0000000000..4098ec11a3 --- /dev/null +++ b/cmd/compose/port_cleanup.go @@ -0,0 +1,44 @@ +package compose + +import ( + "fmt" + "os/exec" + "strings" +) + +func killProcessesUsingExposedPorts(project *types.Project) error { + for _, service := range project.Services { + for _, port := range service.Ports { + exposedPort := port.Published + if exposedPort != "" { + err := killProcessOnPort(exposedPort) + if err != nil { + return err + } + } + } + } + return nil +} + +func killProcessOnPort(port string) error { + cmd := exec.Command("lsof", "-t", "-i", fmt.Sprintf(":%s", port)) + output, err := cmd.Output() + if err != nil { + return fmt.Errorf("failed to find process using port %s: %v", port, err) + } + + pid := strings.TrimSpace(string(output)) + if pid == "" { + return nil + } + + killCmd := exec.Command("kill", "-9", pid) + err = killCmd.Run() + if err != nil { + return fmt.Errorf("failed to kill process %s on port %s: %v", pid, port, err) + } + + fmt.Printf("Killed process %s using port %s\n", pid, port) + return nil +}