Merge pull request #20 from thaJeztah/18.06-backport-do_not_Healthcheck_RUN_command

[18.06] Ensure RUN instruction to run without Healthcheck
diff --git a/builder/dockerfile/dispatchers.go b/builder/dockerfile/dispatchers.go
index 5d72237..c110ab4 100644
--- a/builder/dockerfile/dispatchers.go
+++ b/builder/dockerfile/dispatchers.go
@@ -365,7 +365,8 @@
 	runConfig := copyRunConfig(stateRunConfig,
 		withCmd(cmdFromArgs),
 		withEnv(append(stateRunConfig.Env, buildArgs...)),
-		withEntrypointOverride(saveCmd, strslice.StrSlice{""}))
+		withEntrypointOverride(saveCmd, strslice.StrSlice{""}),
+		withoutHealthcheck())
 
 	// set config as already being escaped, this prevents double escaping on windows
 	runConfig.ArgsEscaped = true
diff --git a/builder/dockerfile/dispatchers_test.go b/builder/dockerfile/dispatchers_test.go
index c61a45b..efa3a1f 100644
--- a/builder/dockerfile/dispatchers_test.go
+++ b/builder/dockerfile/dispatchers_test.go
@@ -473,3 +473,64 @@
 	// Check that runConfig.Cmd has not been modified by run
 	assert.Check(t, is.DeepEqual(origCmd, sb.state.runConfig.Cmd))
 }
+
+func TestRunIgnoresHealthcheck(t *testing.T) {
+	b := newBuilderWithMockBackend()
+	args := NewBuildArgs(make(map[string]*string))
+	sb := newDispatchRequest(b, '`', nil, args, newStagesBuildResults())
+	b.disableCommit = false
+
+	origCmd := strslice.StrSlice([]string{"cmd", "in", "from", "image"})
+
+	imageCache := &mockImageCache{
+		getCacheFunc: func(parentID string, cfg *container.Config) (string, error) {
+			return "", nil
+		},
+	}
+
+	mockBackend := b.docker.(*MockBackend)
+	mockBackend.makeImageCacheFunc = func(_ []string) builder.ImageCache {
+		return imageCache
+	}
+	b.imageProber = newImageProber(mockBackend, nil, false)
+	mockBackend.getImageFunc = func(_ string) (builder.Image, builder.ROLayer, error) {
+		return &mockImage{
+			id:     "abcdef",
+			config: &container.Config{Cmd: origCmd},
+		}, nil, nil
+	}
+	mockBackend.containerCreateFunc = func(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error) {
+		return container.ContainerCreateCreatedBody{ID: "12345"}, nil
+	}
+	mockBackend.commitFunc = func(cfg backend.CommitConfig) (image.ID, error) {
+		return "", nil
+	}
+	from := &instructions.Stage{BaseName: "abcdef"}
+	err := initializeStage(sb, from)
+	assert.NilError(t, err)
+
+	expectedTest := []string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"}
+	cmd := &instructions.HealthCheckCommand{
+		Health: &container.HealthConfig{
+			Test: expectedTest,
+		},
+	}
+	assert.NilError(t, dispatch(sb, cmd))
+	assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
+
+	mockBackend.containerCreateFunc = func(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error) {
+		// Check the Healthcheck is disabled.
+		assert.Check(t, is.DeepEqual([]string{"NONE"}, config.Config.Healthcheck.Test))
+		return container.ContainerCreateCreatedBody{ID: "123456"}, nil
+	}
+
+	sb.state.buildArgs.AddArg("one", strPtr("two"))
+	run := &instructions.RunCommand{
+		ShellDependantCmdLine: instructions.ShellDependantCmdLine{
+			CmdLine:      strslice.StrSlice{"echo foo"},
+			PrependShell: true,
+		},
+	}
+	assert.NilError(t, dispatch(sb, run))
+	assert.Check(t, is.DeepEqual(expectedTest, sb.state.runConfig.Healthcheck.Test))
+}
diff --git a/builder/dockerfile/internals.go b/builder/dockerfile/internals.go
index 1b3a5b0..d892285 100644
--- a/builder/dockerfile/internals.go
+++ b/builder/dockerfile/internals.go
@@ -343,6 +343,18 @@
 	}
 }
 
+// withoutHealthcheck disables healthcheck.
+//
+// The dockerfile RUN instruction expect to run without healthcheck
+// so the runConfig Healthcheck needs to be disabled.
+func withoutHealthcheck() runConfigModifier {
+	return func(runConfig *container.Config) {
+		runConfig.Healthcheck = &container.HealthConfig{
+			Test: []string{"NONE"},
+		}
+	}
+}
+
 func copyRunConfig(runConfig *container.Config, modifiers ...runConfigModifier) *container.Config {
 	copy := *runConfig
 	copy.Cmd = copyStringSlice(runConfig.Cmd)