From c8d3ee80933d6337382fb4a52d90835e263c1aaf Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Sat, 18 Jun 2016 14:16:05 -0700 Subject: [PATCH 1/2] Allow unset `--entrypoint` in `docker run` or `docker create` This fix tries to address the issue raised in #23498 to allow unset `--entrypoint` in `docker run` or `docker create`. This fix checks the flag `--entrypoint` and, in case `--entrypoint=` (`""`) is passed, unset the Entrypoint during the container run. Additional integration tests have been created to cover changes in this fix. This fix fixes #23498. Signed-off-by: Yong Tang --- daemon/create.go | 4 +++ integration-cli/docker_cli_create_test.go | 28 +++++++++++++++++++++ integration-cli/docker_cli_run_test.go | 30 +++++++++++++++++++++++ runconfig/opts/parse.go | 3 +++ 4 files changed, 65 insertions(+) diff --git a/daemon/create.go b/daemon/create.go index 13424f4755..36d1f3c0e9 100644 --- a/daemon/create.go +++ b/daemon/create.go @@ -240,6 +240,10 @@ func (daemon *Daemon) mergeAndVerifyConfig(config *containertypes.Config, img *i return err } } + // Reset the Entrypoint if it is [""] + if len(config.Entrypoint) == 1 && config.Entrypoint[0] == "" { + config.Entrypoint = nil + } if len(config.Entrypoint) == 0 && len(config.Cmd) == 0 { return fmt.Errorf("No command specified") } diff --git a/integration-cli/docker_cli_create_test.go b/integration-cli/docker_cli_create_test.go index ed76353aae..636dc70637 100644 --- a/integration-cli/docker_cli_create_test.go +++ b/integration-cli/docker_cli_create_test.go @@ -478,3 +478,31 @@ func (s *DockerSuite) TestCreate64ByteHexID(c *check.C) { dockerCmd(c, "create", imageID) } + +// Test case for #23498 +func (s *DockerSuite) TestCreateUnsetEntrypoint(c *check.C) { + testRequires(c, DaemonIsLinux) + name := "test-entrypoint" + dockerfile := `FROM busybox +ADD entrypoint.sh /entrypoint.sh +RUN chmod 755 /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] +CMD echo foobar` + + ctx, err := fakeContext(dockerfile, map[string]string{ + "entrypoint.sh": `#!/bin/sh +echo "I am an entrypoint" +exec "$@"`, + }) + c.Assert(err, check.IsNil) + defer ctx.Close() + + _, err = buildImageFromContext(name, ctx, true) + c.Assert(err, check.IsNil) + + out, _ := dockerCmd(c, "create", "--entrypoint=", name, "echo", "foo") + id := strings.TrimSpace(out) + c.Assert(id, check.Not(check.Equals), "") + out, _ = dockerCmd(c, "start", "-a", id) + c.Assert(strings.TrimSpace(out), check.Equals, "foo") +} diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index cf717ffa23..5ac087c03d 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -4497,3 +4497,33 @@ func (s *DockerSuite) TestRunAddHostInHostMode(c *check.C) { out, _ := dockerCmd(c, "run", "--add-host=extra:1.2.3.4", "--net=host", "busybox", "cat", "/etc/hosts") c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out)) } + +// Test case for #23498 +func (s *DockerSuite) TestRunUnsetEntrypoint(c *check.C) { + testRequires(c, DaemonIsLinux) + name := "test-entrypoint" + dockerfile := `FROM busybox +ADD entrypoint.sh /entrypoint.sh +RUN chmod 755 /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] +CMD echo foobar` + + ctx, err := fakeContext(dockerfile, map[string]string{ + "entrypoint.sh": `#!/bin/sh +echo "I am an entrypoint" +exec "$@"`, + }) + c.Assert(err, check.IsNil) + defer ctx.Close() + + _, err = buildImageFromContext(name, ctx, true) + c.Assert(err, check.IsNil) + + out, _ := dockerCmd(c, "run", "--entrypoint=", "-t", name, "echo", "foo") + c.Assert(strings.TrimSpace(out), check.Equals, "foo") + + // CMD will be reset as well (the same as setting a custom entrypoint) + _, _, err = dockerCmdWithError("run", "--entrypoint=", "-t", name) + c.Assert(err, check.NotNil) + c.Assert(err.Error(), checker.Contains, "No command specified") +} diff --git a/runconfig/opts/parse.go b/runconfig/opts/parse.go index 9d2ba67ae6..d1192a3ead 100644 --- a/runconfig/opts/parse.go +++ b/runconfig/opts/parse.go @@ -366,6 +366,9 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c } if copts.flEntrypoint != "" { entrypoint = strslice.StrSlice{copts.flEntrypoint} + } else if flags.Changed("entrypoint") { + // if `--entrypoint=` is parsed then Entrypoint is reset + entrypoint = []string{""} } ports, portBindings, err := nat.ParsePortSpecs(copts.flPublish.GetAll()) From 26c913cb6054236e2df5b4a1fcdc5708c4be8f4c Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Fri, 5 Aug 2016 15:00:41 -0700 Subject: [PATCH 2/2] Update documentation for entrypoint unset with `docker run/create` Signed-off-by: Yong Tang --- docs/reference/api/docker_remote_api_v1.25.md | 4 +++- docs/reference/run.md | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/reference/api/docker_remote_api_v1.25.md b/docs/reference/api/docker_remote_api_v1.25.md index b83ce68cdf..aabd1d06d6 100644 --- a/docs/reference/api/docker_remote_api_v1.25.md +++ b/docs/reference/api/docker_remote_api_v1.25.md @@ -377,7 +377,9 @@ Create a container - **Labels** - Adds a map of labels to a container. To specify a map: `{"key":"value"[,"key2":"value2"]}` - **Cmd** - Command to run specified as a string or an array of strings. - **Entrypoint** - Set the entry point for the container as a string or an array - of strings. + of strings. If the array consists of exactly one empty string (`[""]`) then the entry point + is reset to system default (i.e., the entry point used by docker when there is no `ENTRYPOINT` + instruction in the Dockerfile). - **Image** - A string specifying the image name to use for the container. - **Volumes** - An object mapping mount point paths (strings) inside the container to empty objects. diff --git a/docs/reference/run.md b/docs/reference/run.md index 4f6e679c9e..87fb0e8c81 100644 --- a/docs/reference/run.md +++ b/docs/reference/run.md @@ -1305,6 +1305,10 @@ or two examples of how to pass more parameters to that ENTRYPOINT: $ docker run -it --entrypoint /bin/bash example/redis -c ls -l $ docker run -it --entrypoint /usr/bin/redis-cli example/redis --help +You can reset a containers entrypoint by passing an empty string, for example: + + $ docker run -it --entrypoint="" mysql bash + > **Note**: Passing `--entrypoint` will clear out any default command set on the > image (i.e. any `CMD` instruction in the Dockerfile used to build it).