diff --git a/cmd/nerdctl/container/container_run.go b/cmd/nerdctl/container/container_run.go index b52994dd063..d0d95e1ac43 100644 --- a/cmd/nerdctl/container/container_run.go +++ b/cmd/nerdctl/container/container_run.go @@ -459,11 +459,6 @@ func runAction(cmd *cobra.Command, args []string) error { return err } - statusC, err := task.Wait(ctx) - if err != nil { - return err - } - if err := task.Start(ctx); err != nil { return err } @@ -480,12 +475,14 @@ func runAction(cmd *cobra.Command, args []string) error { return err } - // Setup container healthchecks. - if err := healthcheck.CreateTimer(ctx, c, (*config.Config)(&createOpt.GOptions), createOpt.NerdctlCmd, createOpt.NerdctlArgs); err != nil { - return fmt.Errorf("failed to create healthcheck timer: %w", err) - } - if err := healthcheck.StartTimer(ctx, c, (*config.Config)(&createOpt.GOptions)); err != nil { - return fmt.Errorf("failed to start healthcheck timer: %w", err) + if hcStr, ok := lab[labels.HealthCheck]; ok && hcStr != "" { + // Setup container healthchecks. + if err := healthcheck.CreateTimer(ctx, c, (*config.Config)(&createOpt.GOptions), createOpt.NerdctlCmd, createOpt.NerdctlArgs, lab); err != nil { + return fmt.Errorf("failed to create healthcheck timer: %w", err) + } + if err := healthcheck.StartTimer(ctx, c, (*config.Config)(&createOpt.GOptions), lab); err != nil { + return fmt.Errorf("failed to start healthcheck timer: %w", err) + } } if createOpt.Detach { @@ -503,6 +500,11 @@ func runAction(cmd *cobra.Command, args []string) error { } } + statusC, err := task.Wait(ctx) + if err != nil { + return err + } + select { // io.Wait() would return when either 1) the user detaches from the container OR 2) the container is about to exit. // diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index fa27533f080..52eb8edac90 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -292,6 +292,16 @@ func Start(ctx context.Context, container containerd.Container, isAttach bool, i return err } + if hcStr, ok := lab[labels.HealthCheck]; ok && hcStr != "" { + // If container has health checks configured, create and start systemd timer/service files. + if err := healthcheck.CreateTimer(ctx, container, cfg, nerdctlCmd, nerdctlArgs, lab); err != nil { + return fmt.Errorf("failed to create healthcheck timer: %w", err) + } + if err := healthcheck.StartTimer(ctx, container, cfg, lab); err != nil { + return fmt.Errorf("failed to start healthcheck timer: %w", err) + } + } + // Set status label running should call after task is started. _, restartPolicyExist := lab[restart.PolicyLabel] if restartPolicyExist { @@ -303,14 +313,6 @@ func Start(ctx context.Context, container containerd.Container, isAttach bool, i return err } - // If container has health checks configured, create and start systemd timer/service files. - if err := healthcheck.CreateTimer(ctx, container, cfg, nerdctlCmd, nerdctlArgs); err != nil { - return fmt.Errorf("failed to create healthcheck timer: %w", err) - } - if err := healthcheck.StartTimer(ctx, container, cfg); err != nil { - return fmt.Errorf("failed to start healthcheck timer: %w", err) - } - if !isAttach { return nil } @@ -542,12 +544,19 @@ func Unpause(ctx context.Context, client *containerd.Client, id string, cfg *con return err } - // Recreate healthcheck related systemd timer/service files. - if err := healthcheck.CreateTimer(ctx, container, cfg, nerdctlCmd, nerdctlArgs); err != nil { - return fmt.Errorf("failed to create healthcheck timer: %w", err) + label, err := container.Labels(ctx) + if err != nil { + return err } - if err := healthcheck.StartTimer(ctx, container, cfg); err != nil { - return fmt.Errorf("failed to start healthcheck timer: %w", err) + + if hcStr, ok := label[labels.HealthCheck]; ok && hcStr != "" { + // Recreate healthcheck related systemd timer/service files. + if err := healthcheck.CreateTimer(ctx, container, cfg, nerdctlCmd, nerdctlArgs, label); err != nil { + return fmt.Errorf("failed to create healthcheck timer: %w", err) + } + if err := healthcheck.StartTimer(ctx, container, cfg, label); err != nil { + return fmt.Errorf("failed to start healthcheck timer: %w", err) + } } switch status.Status { diff --git a/pkg/healthcheck/healthcheck_manager_darwin.go b/pkg/healthcheck/healthcheck_manager_darwin.go index f48e5df6a38..5b2d710ce99 100644 --- a/pkg/healthcheck/healthcheck_manager_darwin.go +++ b/pkg/healthcheck/healthcheck_manager_darwin.go @@ -25,12 +25,12 @@ import ( ) // CreateTimer sets up the transient systemd timer and service for healthchecks. -func CreateTimer(ctx context.Context, container containerd.Container, cfg *config.Config, nerdctlCmd string, nerdctlArgs []string) error { +func CreateTimer(ctx context.Context, container containerd.Container, cfg *config.Config, nerdctlCmd string, nerdctlArgs []string, label map[string]string) error { return nil } // StartTimer starts the healthcheck timer unit. -func StartTimer(ctx context.Context, container containerd.Container, cfg *config.Config) error { +func StartTimer(ctx context.Context, container containerd.Container, cfg *config.Config, label map[string]string) error { return nil } diff --git a/pkg/healthcheck/healthcheck_manager_freebsd.go b/pkg/healthcheck/healthcheck_manager_freebsd.go index f48e5df6a38..5b2d710ce99 100644 --- a/pkg/healthcheck/healthcheck_manager_freebsd.go +++ b/pkg/healthcheck/healthcheck_manager_freebsd.go @@ -25,12 +25,12 @@ import ( ) // CreateTimer sets up the transient systemd timer and service for healthchecks. -func CreateTimer(ctx context.Context, container containerd.Container, cfg *config.Config, nerdctlCmd string, nerdctlArgs []string) error { +func CreateTimer(ctx context.Context, container containerd.Container, cfg *config.Config, nerdctlCmd string, nerdctlArgs []string, label map[string]string) error { return nil } // StartTimer starts the healthcheck timer unit. -func StartTimer(ctx context.Context, container containerd.Container, cfg *config.Config) error { +func StartTimer(ctx context.Context, container containerd.Container, cfg *config.Config, label map[string]string) error { return nil } diff --git a/pkg/healthcheck/healthcheck_manager_linux.go b/pkg/healthcheck/healthcheck_manager_linux.go index f3a992c2bc4..5fdd69e7e2f 100644 --- a/pkg/healthcheck/healthcheck_manager_linux.go +++ b/pkg/healthcheck/healthcheck_manager_linux.go @@ -36,8 +36,8 @@ import ( ) // CreateTimer sets up the transient systemd timer and service for healthchecks. -func CreateTimer(ctx context.Context, container containerd.Container, cfg *config.Config, nerdctlCmd string, nerdctlArgs []string) error { - hc := extractHealthcheck(ctx, container) +func CreateTimer(ctx context.Context, container containerd.Container, cfg *config.Config, nerdctlCmd string, nerdctlArgs []string, label map[string]string) error { + hc := extractHealthcheck(ctx, container, label) if hc == nil { return nil } @@ -106,8 +106,8 @@ func createDbusConn(ctx context.Context) (*dbus.Conn, error) { } // StartTimer starts the healthcheck timer unit. -func StartTimer(ctx context.Context, container containerd.Container, cfg *config.Config) error { - hc := extractHealthcheck(ctx, container) +func StartTimer(ctx context.Context, container containerd.Container, cfg *config.Config, label map[string]string) error { + hc := extractHealthcheck(ctx, container, label) if hc == nil { return nil } @@ -135,7 +135,7 @@ func StartTimer(ctx context.Context, container containerd.Container, cfg *config // RemoveTransientHealthCheckFiles stops and cleans up the transient timer and service. func RemoveTransientHealthCheckFiles(ctx context.Context, container containerd.Container) error { - hc := extractHealthcheck(ctx, container) + hc := extractHealthcheck(ctx, container, nil) if hc == nil { return nil } @@ -254,11 +254,17 @@ func ForceRemoveTransientHealthCheckFiles(ctx context.Context, containerID strin return nil } -func extractHealthcheck(ctx context.Context, container containerd.Container) *Healthcheck { - l, err := container.Labels(ctx) - if err != nil { - log.G(ctx).WithError(err).Debugf("could not get labels for container %s", container.ID()) - return nil +func extractHealthcheck(ctx context.Context, container containerd.Container, label map[string]string) *Healthcheck { + var l map[string]string + var err error + if label == nil { + l, err = container.Labels(ctx) + if err != nil { + log.G(ctx).WithError(err).Debugf("could not get labels for container %s", container.ID()) + return nil + } + } else { + l = label } hcStr, ok := l[labels.HealthCheck] if !ok || hcStr == "" { diff --git a/pkg/healthcheck/healthcheck_manager_windows.go b/pkg/healthcheck/healthcheck_manager_windows.go index efd606e7da1..0848a85c935 100644 --- a/pkg/healthcheck/healthcheck_manager_windows.go +++ b/pkg/healthcheck/healthcheck_manager_windows.go @@ -25,12 +25,12 @@ import ( ) // CreateTimer sets up the transient systemd timer and service for healthchecks. -func CreateTimer(ctx context.Context, container containerd.Container, cfg *config.Config, nerdctlCmd string, nerdctlArgs []string) error { +func CreateTimer(ctx context.Context, container containerd.Container, cfg *config.Config, nerdctlCmd string, nerdctlArgs []string, label map[string]string) error { return nil } // StartTimer starts the healthcheck timer unit. -func StartTimer(ctx context.Context, container containerd.Container, cfg *config.Config) error { +func StartTimer(ctx context.Context, container containerd.Container, cfg *config.Config, label map[string]string) error { return nil }