diff --git a/integration/dockerfiles/Dockerfile_test_cmd b/integration/dockerfiles/Dockerfile_test_cmd new file mode 100644 index 0000000000..a2f0162b0a --- /dev/null +++ b/integration/dockerfiles/Dockerfile_test_cmd @@ -0,0 +1,5 @@ +FROM gcr.io/distroless/base@sha256:628939ac8bf3f49571d05c6c76b8688cb4a851af6c7088e599388259875bde20 AS first +CMD ["mycmd"] + +FROM first +ENTRYPOINT ["myentrypoint"] # This should clear out CMD in the config metadata diff --git a/pkg/commands/cmd.go b/pkg/commands/cmd.go index c6965c41ef..3087552002 100644 --- a/pkg/commands/cmd.go +++ b/pkg/commands/cmd.go @@ -23,7 +23,6 @@ import ( "github.com/google/go-containerregistry/pkg/v1" "github.com/moby/buildkit/frontend/dockerfile/instructions" - "github.com/sirupsen/logrus" ) type CmdCommand struct { @@ -48,7 +47,6 @@ func (c *CmdCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui newCommand = c.cmd.CmdLine } - logrus.Infof("Replacing CMD in config with %v", newCommand) config.Cmd = newCommand config.ArgsEscaped = true return nil diff --git a/pkg/commands/entrypoint.go b/pkg/commands/entrypoint.go index ba8aa0c822..5e403e23d2 100644 --- a/pkg/commands/entrypoint.go +++ b/pkg/commands/entrypoint.go @@ -23,7 +23,6 @@ import ( "github.com/google/go-containerregistry/pkg/v1" "github.com/moby/buildkit/frontend/dockerfile/instructions" - "github.com/sirupsen/logrus" ) type EntrypointCommand struct { @@ -47,7 +46,6 @@ func (e *EntrypointCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerf newCommand = e.cmd.CmdLine } - logrus.Infof("Replacing Entrypoint in config with %v", newCommand) config.Entrypoint = newCommand return nil } diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index bcc658fca6..d8fcc722e9 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -55,9 +55,13 @@ const ( S3BuildContextPrefix = "s3://" LocalDirBuildContextPrefix = "dir://" + HOME = "HOME" // DefaultHOMEValue is the default value Docker sets for $HOME - HOME = "HOME" DefaultHOMEValue = "/root" + + // Docker command names + Cmd = "cmd" + Entrypoint = "entrypoint" ) // KanikoBuildFiles is the list of files required to build kaniko diff --git a/pkg/executor/build.go b/pkg/executor/build.go index b908a0beb9..83a6be42b8 100644 --- a/pkg/executor/build.go +++ b/pkg/executor/build.go @@ -194,6 +194,7 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) { if err := sb.build(opts); err != nil { return nil, errors.Wrap(err, "error building stage") } + reviewConfig(stage, &sb.cf.Config) sourceImage, err := mutate.Config(sb.image, sb.cf.Config) if err != nil { return nil, err @@ -277,3 +278,23 @@ func resolveOnBuild(stage *config.KanikoStage, config *v1.Config) error { config.OnBuild = nil return nil } + +// reviewConfig makes sure the value of CMD is correct after building the stage +// If ENTRYPOINT was set in this stage but CMD wasn't, then CMD should be cleared out +// See Issue #346 for more info +func reviewConfig(stage config.KanikoStage, config *v1.Config) { + entrypoint := false + cmd := false + + for _, c := range stage.Commands { + if c.Name() == constants.Cmd { + cmd = true + } + if c.Name() == constants.Entrypoint { + entrypoint = true + } + } + if entrypoint && !cmd { + config.Cmd = nil + } +} diff --git a/pkg/executor/build_test.go b/pkg/executor/build_test.go new file mode 100644 index 0000000000..edf162261a --- /dev/null +++ b/pkg/executor/build_test.go @@ -0,0 +1,76 @@ +/* +Copyright 2018 Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package executor + +import ( + "testing" + + "github.com/GoogleContainerTools/kaniko/pkg/config" + "github.com/GoogleContainerTools/kaniko/pkg/dockerfile" + "github.com/GoogleContainerTools/kaniko/testutil" + "github.com/google/go-containerregistry/pkg/v1" +) + +func Test_reviewConfig(t *testing.T) { + tests := []struct { + name string + dockerfile string + originalCmd []string + originalEntrypoint []string + expectedCmd []string + }{ + { + name: "entrypoint and cmd declared", + dockerfile: ` + FROM scratch + CMD ["mycmd"] + ENTRYPOINT ["myentrypoint"]`, + originalEntrypoint: []string{"myentrypoint"}, + originalCmd: []string{"mycmd"}, + expectedCmd: []string{"mycmd"}, + }, + { + name: "only entrypoint declared", + dockerfile: ` + FROM scratch + ENTRYPOINT ["myentrypoint"]`, + originalEntrypoint: []string{"myentrypoint"}, + originalCmd: []string{"mycmd"}, + expectedCmd: nil, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + config := &v1.Config{ + Cmd: test.originalCmd, + Entrypoint: test.originalEntrypoint, + } + reviewConfig(stage(t, test.dockerfile), config) + testutil.CheckErrorAndDeepEqual(t, false, nil, test.expectedCmd, config.Cmd) + }) + } +} + +func stage(t *testing.T, d string) config.KanikoStage { + stages, err := dockerfile.Parse([]byte(d)) + if err != nil { + t.Fatalf("error parsing dockerfile: %v", err) + } + return config.KanikoStage{ + Stage: stages[0], + } +}