From ac107995ae4a24195f8bb6b70c26393a87d19982 Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 30 Aug 2014 04:34:09 -0700 Subject: [PATCH] builder: Fix entrypoint and cmd semantics in evaluator. Test c/o @cnf Docker-DCO-1.1-Signed-off-by: Erik Hollensbe (github: erikh) --- builder/dispatchers.go | 22 +++++++++++++++++++--- builder/evaluator.go | 2 +- builder/internals.go | 5 +++++ builder/support.go | 6 +++++- integration-cli/docker_cli_build_test.go | 23 ++++++++++++++++++++++- 5 files changed, 52 insertions(+), 6 deletions(-) diff --git a/builder/dispatchers.go b/builder/dispatchers.go index b0c303f3e8..4d1d2135de 100644 --- a/builder/dispatchers.go +++ b/builder/dispatchers.go @@ -168,11 +168,17 @@ func workdir(b *Builder, args []string, attributes map[string]bool) error { func run(b *Builder, args []string, attributes map[string]bool) error { args = handleJsonArgs(args, attributes) + if len(args) == 1 { + args = append([]string{"/bin/sh", "-c"}, args[0]) + } + + args = append([]string{b.image}, args...) + if b.image == "" { return fmt.Errorf("Please provide a source image with `from` prior to run") } - config, _, _, err := runconfig.Parse(append([]string{b.image}, args...), nil) + config, _, _, err := runconfig.Parse(args, nil) if err != nil { return err } @@ -223,11 +229,18 @@ func run(b *Builder, args []string, attributes map[string]bool) error { func cmd(b *Builder, args []string, attributes map[string]bool) error { b.Config.Cmd = handleJsonArgs(args, attributes) + if !attributes["json"] && len(b.Config.Entrypoint) == 0 { + b.Config.Entrypoint = []string{"/bin/sh", "-c"} + } + if err := b.commit("", b.Config.Cmd, fmt.Sprintf("CMD %v", b.Config.Cmd)); err != nil { return err } - b.cmdSet = true + if len(args) != 0 { + b.cmdSet = true + } + return nil } @@ -242,7 +255,10 @@ func cmd(b *Builder, args []string, attributes map[string]bool) error { func entrypoint(b *Builder, args []string, attributes map[string]bool) error { b.Config.Entrypoint = handleJsonArgs(args, attributes) - // if there is no cmd in current Dockerfile - cleanup cmd + if len(b.Config.Entrypoint) == 0 { + b.Config.Entrypoint = []string{"/bin/sh", "-c"} + } + if !b.cmdSet { b.Config.Cmd = nil } diff --git a/builder/evaluator.go b/builder/evaluator.go index 3ab9b3841e..058e08d185 100644 --- a/builder/evaluator.go +++ b/builder/evaluator.go @@ -144,7 +144,7 @@ func (b *Builder) Run(context io.Reader) (string, error) { b.dockerfile = ast // some initializations that would not have been supplied by the caller. - b.Config = &runconfig.Config{} + b.Config = &runconfig.Config{Entrypoint: []string{}, Cmd: []string{"/bin/sh", "-c"}, Env: []string{"PATH=" + daemon.DefaultPathEnv}} b.TmpContainers = map[string]struct{}{} for i, n := range b.dockerfile.Children { diff --git a/builder/internals.go b/builder/internals.go index ac11bb8b1a..4f68525cfb 100644 --- a/builder/internals.go +++ b/builder/internals.go @@ -89,6 +89,11 @@ func (b *Builder) commit(id string, autoCmd []string, comment string) error { // Note: Actually copy the struct autoConfig := *b.Config autoConfig.Cmd = autoCmd + + if autoConfig.Entrypoint == nil { + autoConfig.Entrypoint = []string{"/bin/sh", "-c"} + } + // Commit the container image, err := b.Daemon.Commit(container, "", "", "", b.maintainer, true, &autoConfig) if err != nil { diff --git a/builder/support.go b/builder/support.go index de5d57b501..16fcea5f19 100644 --- a/builder/support.go +++ b/builder/support.go @@ -28,10 +28,14 @@ func (b *Builder) replaceEnv(str string) string { } func handleJsonArgs(args []string, attributes map[string]bool) []string { + if len(args) == 0 { + return []string{} + } + if attributes != nil && attributes["json"] { return args } // literal string command, not an exec array - return append([]string{"/bin/sh", "-c", strings.Join(args, " ")}) + return []string{strings.Join(args, " ")} } diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 7e1d7291ac..1dc8896952 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -1184,7 +1184,7 @@ func TestContextTarNoCompression(t *testing.T) { testContextTar(t, archive.Uncompressed) } -func TestNoContext(t *testing.T) { +func TestBuildNoContext(t *testing.T) { buildCmd := exec.Command(dockerBinary, "build", "-t", "nocontext", "-") buildCmd.Stdin = strings.NewReader("FROM busybox\nCMD echo ok\n") @@ -1899,3 +1899,24 @@ func TestBuildCleanupCmdOnEntrypoint(t *testing.T) { } logDone("build - cleanup cmd on ENTRYPOINT") } + +func TestBuildClearCmd(t *testing.T) { + name := "testbuildclearcmd" + defer deleteImages(name) + _, err := buildImage(name, + `From scratch + ENTRYPOINT ["/bin/bash"] + CMD []`, + true) + if err != nil { + t.Fatal(err) + } + res, err := inspectFieldJSON(name, "Config.Cmd") + if err != nil { + t.Fatal(err) + } + if res != "[]" { + t.Fatalf("Cmd %s, expected %s", res, "[]") + } + logDone("build - clearcmd") +}