diff --git a/daemon/health.go b/daemon/health.go index caa8db8447f23..48cf4c4255be6 100644 --- a/daemon/health.go +++ b/daemon/health.go @@ -64,31 +64,35 @@ type cmdProbe struct { // exec the healthcheck command in the container. // Returns the exit code and probe output (if any) -func (p *cmdProbe) run(ctx context.Context, d *Daemon, container *container.Container) (*types.HealthcheckResult, error) { - - cmdSlice := strslice.StrSlice(container.Config.Healthcheck.Test)[1:] +func (p *cmdProbe) run(ctx context.Context, d *Daemon, cntr *container.Container) (*types.HealthcheckResult, error) { + cmdSlice := strslice.StrSlice(cntr.Config.Healthcheck.Test)[1:] if p.shell { - cmdSlice = append(getShell(container.Config), cmdSlice...) + cmdSlice = append(getShell(cntr.Config), cmdSlice...) } entrypoint, args := d.getEntrypointAndArgs(strslice.StrSlice{}, cmdSlice) execConfig := exec.NewConfig() execConfig.OpenStdin = false execConfig.OpenStdout = true execConfig.OpenStderr = true - execConfig.ContainerID = container.ID + execConfig.ContainerID = cntr.ID execConfig.DetachKeys = []byte{} execConfig.Entrypoint = entrypoint execConfig.Args = args execConfig.Tty = false execConfig.Privileged = false - execConfig.User = container.Config.User - execConfig.Env = container.Config.Env + execConfig.User = cntr.Config.User + + linkedEnv, err := d.setupLinkedContainers(cntr) + if err != nil { + return nil, err + } + execConfig.Env = container.ReplaceOrAppendEnvValues(cntr.CreateDaemonEnvironment(execConfig.Tty, linkedEnv), execConfig.Env) - d.registerExecCommand(container, execConfig) - d.LogContainerEvent(container, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " ")) + d.registerExecCommand(cntr, execConfig) + d.LogContainerEvent(cntr, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " ")) output := &limitedBuffer{} - err := d.ContainerExecStart(ctx, execConfig.ID, nil, output, output) + err = d.ContainerExecStart(ctx, execConfig.ID, nil, output, output) if err != nil { return nil, err } @@ -97,7 +101,7 @@ func (p *cmdProbe) run(ctx context.Context, d *Daemon, container *container.Cont return nil, err } if info.ExitCode == nil { - return nil, fmt.Errorf("Healthcheck for container %s has no exit code!", container.ID) + return nil, fmt.Errorf("Healthcheck for container %s has no exit code!", cntr.ID) } // Note: Go's json package will handle invalid UTF-8 for us out := output.String() diff --git a/integration-cli/docker_cli_health_test.go b/integration-cli/docker_cli_health_test.go index 3e9d048f89111..0f78a41d872c0 100644 --- a/integration-cli/docker_cli_health_test.go +++ b/integration-cli/docker_cli_health_test.go @@ -139,3 +139,26 @@ func (s *DockerSuite) TestHealth(c *check.C) { c.Check(out, checker.Equals, "[CMD cat /my status]\n") } + +// Github #33021 +func (s *DockerSuite) TestUnsetEnvVarHealthCheck(c *check.C) { + testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows + + imageName := "testhealth" + buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox +HEALTHCHECK --interval=1s --timeout=5s --retries=5 CMD /bin/sh -c "sleep 1" +ENTRYPOINT /bin/sh -c "sleep 600"`)) + + name := "env_test_health" + // No health status before starting + dockerCmd(c, "run", "-d", "--name", name, "-e", "FOO", imageName) + defer func() { + dockerCmd(c, "rm", "-f", name) + dockerCmd(c, "rmi", imageName) + }() + + // Start + dockerCmd(c, "start", name) + waitForHealthStatus(c, name, "starting", "healthy") + +}