Modified `docker export` to allow an --output flag
| ... | ... |
@@ -1899,14 +1899,40 @@ func (cli *DockerCli) CmdEvents(args ...string) error {
|
| 1899 | 1899 |
} |
| 1900 | 1900 |
|
| 1901 | 1901 |
func (cli *DockerCli) CmdExport(args ...string) error {
|
| 1902 |
- cmd := cli.Subcmd("export", "CONTAINER", "Export the contents of a filesystem as a tar archive to STDOUT", true)
|
|
| 1902 |
+ cmd := cli.Subcmd("export", "CONTAINER", "Export a filesystem as a tar archive (streamed to STDOUT by default)", true)
|
|
| 1903 |
+ outfile := cmd.String([]string{"o", "-output"}, "", "Write to a file, instead of STDOUT")
|
|
| 1903 | 1904 |
cmd.Require(flag.Exact, 1) |
| 1904 | 1905 |
|
| 1905 | 1906 |
utils.ParseFlags(cmd, args, true) |
| 1906 | 1907 |
|
| 1907 |
- if err := cli.stream("GET", "/containers/"+cmd.Arg(0)+"/export", nil, cli.out, nil); err != nil {
|
|
| 1908 |
- return err |
|
| 1908 |
+ var ( |
|
| 1909 |
+ output io.Writer = cli.out |
|
| 1910 |
+ err error |
|
| 1911 |
+ ) |
|
| 1912 |
+ if *outfile != "" {
|
|
| 1913 |
+ output, err = os.Create(*outfile) |
|
| 1914 |
+ if err != nil {
|
|
| 1915 |
+ return err |
|
| 1916 |
+ } |
|
| 1917 |
+ } else if cli.isTerminalOut {
|
|
| 1918 |
+ return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.")
|
|
| 1919 |
+ } |
|
| 1920 |
+ |
|
| 1921 |
+ if len(cmd.Args()) == 1 {
|
|
| 1922 |
+ image := cmd.Arg(0) |
|
| 1923 |
+ if err := cli.stream("GET", "/containers/"+image+"/export", nil, output, nil); err != nil {
|
|
| 1924 |
+ return err |
|
| 1925 |
+ } |
|
| 1926 |
+ } else {
|
|
| 1927 |
+ v := url.Values{}
|
|
| 1928 |
+ for _, arg := range cmd.Args() {
|
|
| 1929 |
+ v.Add("names", arg)
|
|
| 1930 |
+ } |
|
| 1931 |
+ if err := cli.stream("GET", "/containers/get?"+v.Encode(), nil, output, nil); err != nil {
|
|
| 1932 |
+ return err |
|
| 1933 |
+ } |
|
| 1909 | 1934 |
} |
| 1935 |
+ |
|
| 1910 | 1936 |
return nil |
| 1911 | 1937 |
} |
| 1912 | 1938 |
|
| ... | ... |
@@ -14,17 +14,24 @@ Export the contents of a container's filesystem using the full or shortened |
| 14 | 14 |
container ID or container name. The output is exported to STDOUT and can be |
| 15 | 15 |
redirected to a tar file. |
| 16 | 16 |
|
| 17 |
+Stream to a file instead of STDOUT by using **-o**. |
|
| 18 |
+ |
|
| 17 | 19 |
# OPTIONS |
| 18 | 20 |
**--help** |
| 19 | 21 |
Print usage statement |
| 22 |
+**-o**, **--output**="" |
|
| 23 |
+ Write to a file, instead of STDOUT |
|
| 20 | 24 |
|
| 21 | 25 |
# EXAMPLES |
| 22 | 26 |
Export the contents of the container called angry_bell to a tar file |
| 23 |
-called test.tar: |
|
| 27 |
+called angry_bell.tar: |
|
| 24 | 28 |
|
| 25 |
- # docker export angry_bell > test.tar |
|
| 26 |
- # ls *.tar |
|
| 27 |
- test.tar |
|
| 29 |
+ # docker export angry_bell > angry_bell.tar |
|
| 30 |
+ # docker export --output=angry_bell-latest.tar angry_bell |
|
| 31 |
+ # ls -sh angry_bell.tar |
|
| 32 |
+ 321M angry_bell.tar |
|
| 33 |
+ # ls -sh angry_bell-latest.tar |
|
| 34 |
+ 321M angry_bell-latest.tar |
|
| 28 | 35 |
|
| 29 | 36 |
# See also |
| 30 | 37 |
**docker-import(1)** to create an empty filesystem image |
| ... | ... |
@@ -34,3 +41,4 @@ and import the contents of the tarball into it, then optionally tag it. |
| 34 | 34 |
April 2014, Originally compiled by William Henry (whenry at redhat dot com) |
| 35 | 35 |
based on docker.com source material and internal work. |
| 36 | 36 |
June 2014, updated by Sven Dowideit <SvenDowideit@home.org.au> |
| 37 |
+Janurary 2015, updated by Joseph Kern (josephakern at gmail dot com) |
| ... | ... |
@@ -1068,14 +1068,22 @@ This will create a new Bash session in the container `ubuntu_bash`. |
| 1068 | 1068 |
|
| 1069 | 1069 |
## export |
| 1070 | 1070 |
|
| 1071 |
- Usage: docker export CONTAINER |
|
| 1071 |
+ Usage: docker export [OPTIONS] CONTAINER |
|
| 1072 | 1072 |
|
| 1073 |
- Export the contents of a filesystem as a tar archive to STDOUT |
|
| 1073 |
+ Export the contents of a filesystem to a tar archive (streamed to STDOUT by default) |
|
| 1074 | 1074 |
|
| 1075 |
-For example: |
|
| 1075 |
+ -o, --output="" Write to a file, instead of STDOUT |
|
| 1076 |
+ |
|
| 1077 |
+ Produces a tarred repository to the standard output stream. |
|
| 1078 |
+ |
|
| 1079 |
+ For example: |
|
| 1076 | 1080 |
|
| 1077 | 1081 |
$ sudo docker export red_panda > latest.tar |
| 1078 | 1082 |
|
| 1083 |
+ Or |
|
| 1084 |
+ |
|
| 1085 |
+ $ sudo docker export --output="latest.tar" red_panda |
|
| 1086 |
+ |
|
| 1079 | 1087 |
> **Note:** |
| 1080 | 1088 |
> `docker export` does not export the contents of volumes associated with the |
| 1081 | 1089 |
> container. If a volume is mounted on top of an existing directory in the |
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package main |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "os" |
|
| 4 | 5 |
"os/exec" |
| 5 | 6 |
"strings" |
| 6 | 7 |
"testing" |
| ... | ... |
@@ -47,3 +48,52 @@ func TestExportContainerAndImportImage(t *testing.T) {
|
| 47 | 47 |
logDone("export - export a container")
|
| 48 | 48 |
logDone("import - import an image")
|
| 49 | 49 |
} |
| 50 |
+ |
|
| 51 |
+// Used to test output flag in the export command |
|
| 52 |
+func TestExportContainerWithOutputAndImportImage(t *testing.T) {
|
|
| 53 |
+ runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") |
|
| 54 |
+ out, _, err := runCommandWithOutput(runCmd) |
|
| 55 |
+ if err != nil {
|
|
| 56 |
+ t.Fatal("failed to create a container", out, err)
|
|
| 57 |
+ } |
|
| 58 |
+ |
|
| 59 |
+ cleanedContainerID := stripTrailingCharacters(out) |
|
| 60 |
+ |
|
| 61 |
+ inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID) |
|
| 62 |
+ out, _, err = runCommandWithOutput(inspectCmd) |
|
| 63 |
+ if err != nil {
|
|
| 64 |
+ t.Fatalf("output should've been a container id: %s %s ", cleanedContainerID, err)
|
|
| 65 |
+ } |
|
| 66 |
+ |
|
| 67 |
+ exportCmd := exec.Command(dockerBinary, "export", "--output=testexp.tar", cleanedContainerID) |
|
| 68 |
+ if out, _, err = runCommandWithOutput(exportCmd); err != nil {
|
|
| 69 |
+ t.Fatalf("failed to export container: %s, %v", out, err)
|
|
| 70 |
+ } |
|
| 71 |
+ |
|
| 72 |
+ out, _, err = runCommandWithOutput(exec.Command("cat", "testexp.tar"))
|
|
| 73 |
+ if err != nil {
|
|
| 74 |
+ t.Fatal(out, err) |
|
| 75 |
+ } |
|
| 76 |
+ |
|
| 77 |
+ importCmd := exec.Command(dockerBinary, "import", "-", "repo/testexp:v1") |
|
| 78 |
+ importCmd.Stdin = strings.NewReader(out) |
|
| 79 |
+ out, _, err = runCommandWithOutput(importCmd) |
|
| 80 |
+ if err != nil {
|
|
| 81 |
+ t.Fatalf("failed to import image: %s, %v", out, err)
|
|
| 82 |
+ } |
|
| 83 |
+ |
|
| 84 |
+ cleanedImageID := stripTrailingCharacters(out) |
|
| 85 |
+ |
|
| 86 |
+ inspectCmd = exec.Command(dockerBinary, "inspect", cleanedImageID) |
|
| 87 |
+ if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
|
|
| 88 |
+ t.Fatalf("output should've been an image id: %s, %v", out, err)
|
|
| 89 |
+ } |
|
| 90 |
+ |
|
| 91 |
+ deleteContainer(cleanedContainerID) |
|
| 92 |
+ deleteImages("repo/testexp:v1")
|
|
| 93 |
+ |
|
| 94 |
+ os.Remove("/tmp/testexp.tar")
|
|
| 95 |
+ |
|
| 96 |
+ logDone("export - export a container with output flag")
|
|
| 97 |
+ logDone("import - import an image with output flag")
|
|
| 98 |
+} |