Browse Source

use log API for containers we didn't attached to

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 4 months ago
parent
commit
2c12ad19db
2 changed files with 35 additions and 31 deletions
  1. 1 14
      pkg/compose/start.go
  2. 34 17
      pkg/compose/up.go

+ 1 - 14
pkg/compose/start.go

@@ -28,7 +28,6 @@ import (
 
 	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/docker/api/types/filters"
-	"golang.org/x/sync/errgroup"
 )
 
 func (s *composeService) Start(ctx context.Context, projectName string, options api.StartOptions) error {
@@ -52,18 +51,6 @@ func (s *composeService) start(ctx context.Context, projectName string, options
 		}
 	}
 
-	// use an independent context tied to the errgroup for background attach operations
-	// the primary context is still used for other operations
-	// this means that once any attach operation fails, all other attaches are cancelled,
-	// but an attach failing won't interfere with the rest of the start
-	eg, attachCtx := errgroup.WithContext(ctx)
-	if listener != nil {
-		_, err := s.attach(attachCtx, project, listener, options.AttachTo)
-		if err != nil {
-			return err
-		}
-	}
-
 	var containers Containers
 	containers, err := s.apiClient().ContainerList(ctx, containerType.ListOptions{
 		Filters: filters.NewArgs(
@@ -111,7 +98,7 @@ func (s *composeService) start(ctx context.Context, projectName string, options
 		}
 	}
 
-	return eg.Wait()
+	return nil
 }
 
 // getDependencyCondition checks if service is depended on by other services

+ 34 - 17
pkg/compose/up.go

@@ -21,6 +21,7 @@ import (
 	"fmt"
 	"os"
 	"os/signal"
+	"slices"
 	"sync/atomic"
 	"syscall"
 
@@ -34,6 +35,7 @@ import (
 	"github.com/eiannone/keyboard"
 	"github.com/hashicorp/go-multierror"
 	"github.com/sirupsen/logrus"
+	"golang.org/x/sync/errgroup"
 )
 
 func (s *composeService) Up(ctx context.Context, project *types.Project, options api.UpOptions) error { //nolint:gocyclo
@@ -205,29 +207,44 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
 		})
 	}
 
+	// use an independent context tied to the errgroup for background attach operations
+	// the primary context is still used for other operations
+	// this means that once any attach operation fails, all other attaches are cancelled,
+	// but an attach failing won't interfere with the rest of the start
+	_, attachCtx := errgroup.WithContext(ctx)
+	containers, err := s.attach(attachCtx, project, printer.HandleEvent, options.Start.AttachTo)
+	if err != nil {
+		return err
+	}
+	attached := make([]string, len(containers))
+	for i, ctr := range containers {
+		attached[i] = ctr.ID
+	}
+
 	monitor.withListener(func(event api.ContainerEvent) {
 		if event.Type != api.ContainerEventStarted {
 			return
 		}
-		if event.Restarting || event.Container.Labels[api.ContainerReplaceLabel] != "" {
-			eg.Go(func() error {
-				ctr, err := s.apiClient().ContainerInspect(ctx, event.ID)
-				if err != nil {
-					return err
-				}
-
-				err = s.doLogContainer(ctx, options.Start.Attach, event.Source, ctr, api.LogOptions{
-					Follow: true,
-					Since:  ctr.State.StartedAt,
-				})
-				if errdefs.IsNotImplemented(err) {
-					// container may be configured with logging_driver: none
-					// as container already started, we might miss the very first logs. But still better than none
-					return s.doAttachContainer(ctx, event.Service, event.ID, event.Source, printer.HandleEvent)
-				}
+		if slices.Contains(attached, event.ID) {
+			return
+		}
+		eg.Go(func() error {
+			ctr, err := s.apiClient().ContainerInspect(ctx, event.ID)
+			if err != nil {
 				return err
+			}
+
+			err = s.doLogContainer(ctx, options.Start.Attach, event.Source, ctr, api.LogOptions{
+				Follow: true,
+				Since:  ctr.State.StartedAt,
 			})
-		}
+			if errdefs.IsNotImplemented(err) {
+				// container may be configured with logging_driver: none
+				// as container already started, we might miss the very first logs. But still better than none
+				return s.doAttachContainer(ctx, event.Service, event.ID, event.Source, printer.HandleEvent)
+			}
+			return err
+		})
 	})
 
 	eg.Go(func() error {