diff --git a/api/client/import.go b/api/client/import.go index ec3d028f90..9bb8818cd3 100644 --- a/api/client/import.go +++ b/api/client/import.go @@ -23,6 +23,7 @@ func (cli *DockerCli) CmdImport(args ...string) error { cmd := Cli.Subcmd("import", []string{"file|URL|- [REPOSITORY[:TAG]]"}, "Create an empty filesystem image and import the contents of the\ntarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) into it, then\noptionally tag it.", true) flChanges := opts.NewListOpts(nil) cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image") + message := cmd.String([]string{"m", "-message"}, "", "Set commit message for imported image") cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) @@ -35,6 +36,7 @@ func (cli *DockerCli) CmdImport(args ...string) error { v.Set("fromSrc", src) v.Set("repo", repository) + v.Set("message", *message) for _, change := range flChanges.GetAll() { v.Add("changes", change) } diff --git a/api/server/image.go b/api/server/image.go index c929fced37..55b66c1db8 100644 --- a/api/server/image.go +++ b/api/server/image.go @@ -70,9 +70,10 @@ func (s *Server) postImagesCreate(version version.Version, w http.ResponseWriter } var ( - image = r.Form.Get("fromImage") - repo = r.Form.Get("repo") - tag = r.Form.Get("tag") + image = r.Form.Get("fromImage") + repo = r.Form.Get("repo") + tag = r.Form.Get("tag") + message = r.Form.Get("message") ) authEncoded := r.Header.Get("X-Registry-Auth") authConfig := &cliconfig.AuthConfig{} @@ -126,7 +127,7 @@ func (s *Server) postImagesCreate(version version.Version, w http.ResponseWriter return err } - err = s.daemon.Repositories().Import(src, repo, tag, r.Body, output, newConfig) + err = s.daemon.Repositories().Import(src, repo, tag, message, r.Body, output, newConfig) } if err != nil { if !output.Flushed() { diff --git a/docs/reference/commandline/import.md b/docs/reference/commandline/import.md index 20c790d21d..92bf878a1c 100644 --- a/docs/reference/commandline/import.md +++ b/docs/reference/commandline/import.md @@ -18,6 +18,7 @@ weight=1 optionally tag it. -c, --change=[] Apply specified Dockerfile instructions while importing the image + -m, --message= Set commit message for imported image You can specify a `URL` or `-` (dash) to take data directly from `STDIN`. The `URL` can point to an archive (.tar, .tar.gz, .tgz, .bzip, .tar.xz, or .txz) @@ -46,6 +47,10 @@ Import to docker via pipe and `STDIN`. $ cat exampleimage.tgz | docker import - exampleimagelocal:new +Import with a commit message + + $ cat exampleimage.tgz | docker import --message "New image imported from tarball" - exampleimagelocal:new + Import to docker from a local archive. $ docker import /path/to/exampleimage.tgz diff --git a/graph/import.go b/graph/import.go index 5a7976d5e6..1a09dec470 100644 --- a/graph/import.go +++ b/graph/import.go @@ -16,7 +16,7 @@ import ( // inConfig (if src is "-"), or from a URI specified in src. Progress output is // written to outStream. Repository and tag names can optionally be given in // the repo and tag arguments, respectively. -func (s *TagStore) Import(src string, repo string, tag string, inConfig io.ReadCloser, outStream io.Writer, containerConfig *runconfig.Config) error { +func (s *TagStore) Import(src string, repo string, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, containerConfig *runconfig.Config) error { var ( sf = streamformatter.NewJSONStreamFormatter() archive io.ReadCloser @@ -54,7 +54,11 @@ func (s *TagStore) Import(src string, repo string, tag string, inConfig io.ReadC } defer archive.Close() - img, err := s.graph.Create(archive, "", "", "Imported from "+src, "", nil, containerConfig) + if len(msg) == 0 { + msg = "Imported from " + src + } + + img, err := s.graph.Create(archive, "", "", msg, "", nil, containerConfig) if err != nil { return err } diff --git a/integration-cli/docker_cli_import_test.go b/integration-cli/docker_cli_import_test.go index d3e60e1490..9ba66a14b3 100644 --- a/integration-cli/docker_cli_import_test.go +++ b/integration-cli/docker_cli_import_test.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "os" "os/exec" + "regexp" "strings" "github.com/go-check/check" @@ -72,6 +73,49 @@ func (s *DockerSuite) TestImportFile(c *check.C) { } } +func (s *DockerSuite) TestImportFileWithMessage(c *check.C) { + dockerCmd(c, "run", "--name", "test-import", "busybox", "true") + + temporaryFile, err := ioutil.TempFile("", "exportImportTest") + if err != nil { + c.Fatal("failed to create temporary file", "", err) + } + defer os.Remove(temporaryFile.Name()) + + runCmd := exec.Command(dockerBinary, "export", "test-import") + runCmd.Stdout = bufio.NewWriter(temporaryFile) + + _, err = runCommand(runCmd) + if err != nil { + c.Fatal("failed to export a container", err) + } + + message := "Testing commit message" + out, _ := dockerCmd(c, "import", "-m", message, temporaryFile.Name()) + if n := strings.Count(out, "\n"); n != 1 { + c.Fatalf("display is messed up: %d '\\n' instead of 1:\n%s", n, out) + } + image := strings.TrimSpace(out) + + out, _ = dockerCmd(c, "history", image) + split := strings.Split(out, "\n") + + if len(split) != 3 { + c.Fatalf("expected 3 lines from image history, got %d", len(split)) + } + r := regexp.MustCompile("[\\s]{2,}") + split = r.Split(split[1], -1) + + if message != split[3] { + c.Fatalf("expected %s in commit message, got %s", message, split[3]) + } + + out, _ = dockerCmd(c, "run", "--rm", image, "true") + if out != "" { + c.Fatalf("command output should've been nothing, was %q", out) + } +} + func (s *DockerSuite) TestImportFileNonExistentFile(c *check.C) { _, exitCode, err := dockerCmdWithError("import", "example.com/myImage.tar") if exitCode == 0 || err == nil { diff --git a/man/docker-import.1.md b/man/docker-import.1.md index 5ac686677b..b812b83068 100644 --- a/man/docker-import.1.md +++ b/man/docker-import.1.md @@ -7,6 +7,7 @@ docker-import - Create an empty filesystem image and import the contents of the # SYNOPSIS **docker import** [**-c**|**--change**[= []**]] +[**-m**|**--message**[=*MESSAGE*]] [**--help**] file|URL|- [REPOSITORY[:TAG]] @@ -15,6 +16,9 @@ file|URL|- [REPOSITORY[:TAG]] Apply specified Dockerfile instructions while importing the image Supported Dockerfile instructions: `CMD`|`ENTRYPOINT`|`ENV`|`EXPOSE`|`ONBUILD`|`USER`|`VOLUME`|`WORKDIR` +**-m**, **--message**="" + Set commit message for imported image + # DESCRIPTION Create a new filesystem image from the contents of a tarball (`.tar`, `.tar.gz`, `.tgz`, `.bzip`, `.tar.xz`, `.txz`) into it, then optionally tag it. @@ -35,6 +39,10 @@ Import to docker via pipe and stdin: # cat exampleimage.tgz | docker import - example/imagelocal +Import with a commit message + + # cat exampleimage.tgz | docker import --message "New image imported from tarball" - exampleimagelocal:new + Import to a Docker image from a local file. # docker import /path/to/exampleimage.tgz