فهرست منبع

work on #11094 allow import from local file

Signed-off-by: Gildas Cuisinier <gildas.cuisinier@gcuisinier.net>
Gildas Cuisinier 10 سال پیش
والد
کامیت
3f64b76d4c
4فایلهای تغییر یافته به همراه90 افزوده شده و 10 حذف شده
  1. 15 4
      api/client/import.go
  2. 13 5
      docs/reference/commandline/cli.md
  3. 56 0
      integration-cli/docker_cli_import_test.go
  4. 6 1
      man/docker-import.1.md

+ 15 - 4
api/client/import.go

@@ -4,20 +4,22 @@ import (
 	"fmt"
 	"fmt"
 	"io"
 	"io"
 	"net/url"
 	"net/url"
+	"os"
 
 
 	"github.com/docker/docker/opts"
 	"github.com/docker/docker/opts"
 	flag "github.com/docker/docker/pkg/mflag"
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/parsers"
+	"github.com/docker/docker/pkg/urlutil"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/registry"
 )
 )
 
 
 // CmdImport creates an empty filesystem image, imports the contents of the tarball into the image, and optionally tags the image.
 // CmdImport creates an empty filesystem image, imports the contents of the tarball into the image, and optionally tags the image.
 //
 //
-// The URL argument is the address of a tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) file. If the URL is '-', then the tar file is read from STDIN.
+// The URL argument is the address of a tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) file or a path to local file relative to docker client. If the URL is '-', then the tar file is read from STDIN.
 //
 //
-// Usage: docker import [OPTIONS] URL [REPOSITORY[:TAG]]
+// Usage: docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
 func (cli *DockerCli) CmdImport(args ...string) error {
 func (cli *DockerCli) CmdImport(args ...string) error {
-	cmd := cli.Subcmd("import", []string{"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)
+	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)
 	flChanges := opts.NewListOpts(nil)
 	cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image")
 	cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image")
 	cmd.Require(flag.Min, 1)
 	cmd.Require(flag.Min, 1)
@@ -36,7 +38,7 @@ func (cli *DockerCli) CmdImport(args ...string) error {
 		v.Add("changes", change)
 		v.Add("changes", change)
 	}
 	}
 	if cmd.NArg() == 3 {
 	if cmd.NArg() == 3 {
-		fmt.Fprintf(cli.err, "[DEPRECATED] The format 'URL|- [REPOSITORY [TAG]]' has been deprecated. Please use URL|- [REPOSITORY[:TAG]]\n")
+		fmt.Fprintf(cli.err, "[DEPRECATED] The format 'file|URL|- [REPOSITORY [TAG]]' has been deprecated. Please use file|URL|- [REPOSITORY[:TAG]]\n")
 		v.Set("tag", cmd.Arg(2))
 		v.Set("tag", cmd.Arg(2))
 	}
 	}
 
 
@@ -52,6 +54,15 @@ func (cli *DockerCli) CmdImport(args ...string) error {
 
 
 	if src == "-" {
 	if src == "-" {
 		in = cli.in
 		in = cli.in
+	} else if !urlutil.IsURL(src) {
+		v.Set("fromSrc", "-")
+		file, err := os.Open(src)
+		if err != nil {
+			return err
+		}
+		defer file.Close()
+		in = file
+
 	}
 	}
 
 
 	sopts := &streamOpts{
 	sopts := &streamOpts{

+ 13 - 5
docs/reference/commandline/cli.md

@@ -1455,7 +1455,7 @@ NOTE: Docker will warn you if any containers exist that are using these untagged
 
 
 ## import
 ## import
 
 
-    Usage: docker import URL|- [REPOSITORY[:TAG]]
+    Usage: docker import file|URL|- [REPOSITORY[:TAG]]
 
 
     Create an empty filesystem image and import the contents of the
     Create an empty filesystem image and import the contents of the
 	tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) into it, then
 	tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) into it, then
@@ -1463,10 +1463,14 @@ NOTE: Docker will warn you if any containers exist that are using these untagged
 
 
       -c, --change=[]     Apply specified Dockerfile instructions while importing the image
       -c, --change=[]     Apply specified Dockerfile instructions while importing the image
 
 
-URLs must start with `http` and point to a single file archive (.tar,
-.tar.gz, .tgz, .bzip, .tar.xz, or .txz) containing a root filesystem. If
-you would like to import from a local directory or archive, you can use
-the `-` parameter to take the data from `STDIN`.
+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)
+containing a fileystem or to an individual file on the Docker host.  If you
+specify an archive, Docker untars it in the container relative to the `/`
+(root). If you specify an individual file, you must specify the full path within
+the host. To import from a remote location, specify a `URI` that begins with the
+`http://` or `https://` protocol.
+
 
 
 The `--change` option will apply `Dockerfile` instructions to the image
 The `--change` option will apply `Dockerfile` instructions to the image
 that is created.
 that is created.
@@ -1475,6 +1479,10 @@ Supported `Dockerfile` instructions:
 
 
 #### Examples
 #### Examples
 
 
+**Import from a local file archive:**
+
+    $ sudo docker import /local/path/to/exampleimage.tgz exampleimagedir
+
 **Import from a remote location:**
 **Import from a remote location:**
 
 
 This will create a new untagged image.
 This will create a new untagged image.

+ 56 - 0
integration-cli/docker_cli_import_test.go

@@ -1,6 +1,9 @@
 package main
 package main
 
 
 import (
 import (
+	"bufio"
+	"io/ioutil"
+	"os"
 	"os/exec"
 	"os/exec"
 	"strings"
 	"strings"
 
 
@@ -50,3 +53,56 @@ func (s *DockerSuite) TestImportBadURL(c *check.C) {
 		c.Fatalf("expected an error msg but didn't get one:\n%s", out)
 		c.Fatalf("expected an error msg but didn't get one:\n%s", out)
 	}
 	}
 }
 }
+
+func (s *DockerSuite) TestImportFile(c *check.C) {
+	runCmd := exec.Command(dockerBinary, "run", "--name", "test-import", "busybox", "true")
+	out, _, err := runCommandWithOutput(runCmd)
+	if err != nil {
+		c.Fatal("failed to create a container", out, err)
+	}
+
+	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", out, err)
+	}
+
+	runCmd = exec.Command(dockerBinary, "import", temporaryFile.Name())
+	out, _, err = runCommandWithOutput(runCmd)
+	if err != nil {
+		c.Fatal("failed to import a container", out, err)
+	}
+
+	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)
+
+	runCmd = exec.Command(dockerBinary, "run", "--rm", image, "true")
+	out, _, err = runCommandWithOutput(runCmd)
+	if err != nil {
+		c.Fatal("failed to create a container", out, err)
+	}
+
+	if out != "" {
+		c.Fatalf("command output should've been nothing, was %q", out)
+	}
+
+}
+
+func (s *DockerSuite) TestImportFileNonExistentFile(c *check.C) {
+	runCmd := exec.Command(dockerBinary, "import", "example.com/myImage.tar")
+	_, exitCode, err := runCommandWithOutput(runCmd)
+	if exitCode == 0 || err == nil {
+		c.Fatalf("import non-existing file must failed")
+	}
+
+}

+ 6 - 1
man/docker-import.1.md

@@ -8,7 +8,7 @@ docker-import - Create an empty filesystem image and import the contents of the
 **docker import**
 **docker import**
 [**-c**|**--change**[= []**]]
 [**-c**|**--change**[= []**]]
 [**--help**]
 [**--help**]
-URL|- [REPOSITORY[:TAG]]
+file|URL|- [REPOSITORY[:TAG]]
 
 
 # OPTIONS
 # OPTIONS
 **-c**, **--change**=[]
 **-c**, **--change**=[]
@@ -35,6 +35,11 @@ Import to docker via pipe and stdin:
 
 
     # cat exampleimage.tgz | docker import - example/imagelocal
     # cat exampleimage.tgz | docker import - example/imagelocal
 
 
+Import to a Docker image from a local file.
+
+    # docker import /path/to/exampleimage.tgz 
+
+
 ## Import from a local file and tag
 ## Import from a local file and tag
 
 
 Import to docker via pipe and stdin:
 Import to docker via pipe and stdin: