MCPcopy
hub / github.com/docker/compose / runPreStartHook

Method runPreStartHook

pkg/compose/pre_start.go:75–123  ·  pkg/compose/pre_start.go::composeService.runPreStartHook
(
	ctx context.Context, project *types.Project, service types.ServiceConfig,
	ctr container.Summary, index int, hook types.ServiceHook, listener api.ContainerEventListener,
)

Source from the content-addressed store, hash-verified

73}
74
75func (s *composeService) runPreStartHook(
76 ctx context.Context, project *types.Project, service types.ServiceConfig,
77 ctr container.Summary, index int, hook types.ServiceHook, listener api.ContainerEventListener,
78) error {
79 created, err := s.createPreStartContainer(ctx, project, service, ctr, hook)
80 if err != nil {
81 return err
82 }
83
84 // Subscribe to wait before start to avoid missing the exit event for short-lived hooks.
85 // WaitConditionNotRunning would match immediately because the container is still in
86 // "created" state, so use WaitConditionNextExit to block until the run actually finishes.
87 waitRes := s.apiClient().ContainerWait(ctx, created.ID, client.ContainerWaitOptions{
88 Condition: container.WaitConditionNextExit,
89 })
90
91 // Open the log stream before ContainerStart so AutoRemove cannot race us
92 // to a 404 on a fast-exiting hook. The dedicated logCtx lets us force the
93 // follow stream closed once the hook has exited, so a daemon that keeps
94 // the connection open cannot deadlock `<-logsDone`.
95 logCtx, cancelLogs := context.WithCancel(ctx)
96 defer cancelLogs()
97 logsDone := s.streamPreStartLogs(logCtx, created.ID, service, index, listener)
98
99 if _, err := s.apiClient().ContainerStart(ctx, created.ID, client.ContainerStartOptions{}); err != nil {
100 // AutoRemove only fires after a successful start, so the never-started
101 // container has to be dropped explicitly. A failed removal is logged
102 // at warn level — without that hint the orphan is only discoverable
103 // via the project/service labels.
104 if _, removeErr := s.apiClient().ContainerRemove(ctx, created.ID, client.ContainerRemoveOptions{Force: true}); removeErr != nil {
105 logrus.Warnf("service %q pre_start[%d]: failed to remove orphan hook container %s: %v", service.Name, index, created.ID, removeErr)
106 }
107 // Drain waitRes so the client's wait goroutine exits without having to
108 // wait for the parent context to be canceled.
109 select {
110 case <-waitRes.Error:
111 case <-waitRes.Result:
112 case <-ctx.Done():
113 }
114 cancelLogs()
115 <-logsDone
116 return err
117 }
118
119 waitErr := waitPreStart(ctx, service.Name, index, waitRes)
120 cancelLogs()
121 <-logsDone
122 return waitErr
123}
124
125func (s *composeService) createPreStartContainer(
126 ctx context.Context, project *types.Project, service types.ServiceConfig,

Callers 1

runPreStartMethod · 0.95

Calls 8

apiClientMethod · 0.95
streamPreStartLogsMethod · 0.95
waitPreStartFunction · 0.85
DoneMethod · 0.65
ContainerWaitMethod · 0.45
ContainerStartMethod · 0.45
ContainerRemoveMethod · 0.45

Tested by

no test coverage detected