diff --git a/pkg/compose/down.go b/pkg/compose/down.go index 6e408ef87..b4bbc6e3c 100644 --- a/pkg/compose/down.go +++ b/pkg/compose/down.go @@ -311,7 +311,7 @@ func (s *composeService) stopContainer(ctx context.Context, service *types.Servi eventName := getContainerProgressName(ctr) s.events.On(newEvent(eventName, api.Working, api.StatusStopping)) - if service != nil { + if service != nil && !isRelayContainer(ctr) { for _, hook := range service.PreStop { err := s.runHook(ctx, ctr, *service, hook, listener) if err != nil { diff --git a/pkg/compose/down_test.go b/pkg/compose/down_test.go index cd0aba534..d8fa9338f 100644 --- a/pkg/compose/down_test.go +++ b/pkg/compose/down_test.go @@ -676,6 +676,27 @@ func TestDownHookContainerRemovalFailureIsNonFatal(t *testing.T) { assert.NilError(t, err) } +// A relay stands in for the service on the network but is a shell-less +// scratch binary: pre_stop has no process inside it to act on. No +// ExecCreate expectation is set: per newStartTestService, gomock fails the +// test if the hook still runs. +func TestStopContainerSkipsPreStopForRelay(t *testing.T) { + svc, apiClient, _ := newStartTestService(t) + + service := types.ServiceConfig{ + Name: "db", + PreStop: []types.ServiceHook{{Command: types.ShellCommand{"quiesce"}}}, + } + relay := serviceContainer("db", 1, container.StateRunning) + relay.Labels[compose.RelayLabel] = "abc123" + + apiClient.EXPECT().ContainerStop(gomock.Any(), relay.ID, gomock.Any()). + Return(client.ContainerStopResult{}, nil) + + err := svc.stopContainer(t.Context(), &service, relay, nil, nil) + assert.NilError(t, err) +} + // runningOneOff builds a RUNNING `compose run` container of the given service. func runningOneOff(service, id string) container.Summary { c := testContainer(service, id, true)