diff --git a/api/client/commands.go b/api/client/commands.go index a4835bbeb3..291390a53e 100644 --- a/api/client/commands.go +++ b/api/client/commands.go @@ -2415,7 +2415,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { } func (cli *DockerCli) CmdCp(args ...string) error { - cmd := cli.Subcmd("cp", "CONTAINER:PATH HOSTPATH", "Copy files/folders from the PATH to the HOSTPATH", true) + cmd := cli.Subcmd("cp", "CONTAINER:PATH HOSTPATH|-", "Copy files/folders from the PATH to the HOSTPATH. Use '-' to write the data\nas a tar file to STDOUT.", true) cmd.Require(flag.Exact, 2) utils.ParseFlags(cmd, args, true) @@ -2442,7 +2442,14 @@ func (cli *DockerCli) CmdCp(args ...string) error { } if statusCode == 200 { - if err := archive.Untar(stream, copyData.Get("HostPath"), &archive.TarOptions{NoLchown: true}); err != nil { + dest := copyData.Get("HostPath") + + if dest == "-" { + _, err = io.Copy(cli.out, stream) + } else { + err = archive.Untar(stream, dest, &archive.TarOptions{NoLchown: true}) + } + if err != nil { return err } } diff --git a/docs/man/docker-cp.1.md b/docs/man/docker-cp.1.md index ac49a47a54..71d57e35c3 100644 --- a/docs/man/docker-cp.1.md +++ b/docs/man/docker-cp.1.md @@ -2,16 +2,17 @@ % Docker Community % JUNE 2014 # NAME -docker-cp - Copy files/folders from the PATH to the HOSTPATH +docker-cp - Copy files/folders from the PATH to the HOSTPATH, or STDOUT # SYNOPSIS **docker cp** [**--help**] -CONTAINER:PATH HOSTPATH +CONTAINER:PATH HOSTPATH|- # DESCRIPTION -Copy files/folders from a container's filesystem to the host -path. Paths are relative to the root of the filesystem. Files +Copy files/folders from a container's filesystem to the +path. Use '-' to write the data as a tar file to STDOUT. +Paths are relative to the root of the filesystem. Files can be copied from a running or stopped container. # OPTIONS diff --git a/docs/man/docker.1.md b/docs/man/docker.1.md index 4a6d0cf152..1b5288bbb5 100644 --- a/docs/man/docker.1.md +++ b/docs/man/docker.1.md @@ -117,7 +117,7 @@ unix://[/path/to/socket] to use. Create a new image from a container's changes **docker-cp(1)** - Copy files/folders from a container's filesystem to the host at path + Copy files/folders from a container's filesystem to the host **docker-create(1)** Create a new container diff --git a/docs/sources/reference/commandline/cli.md b/docs/sources/reference/commandline/cli.md index eb61872dae..25a4be44bf 100644 --- a/docs/sources/reference/commandline/cli.md +++ b/docs/sources/reference/commandline/cli.md @@ -757,12 +757,15 @@ Supported `Dockerfile` instructions: `CMD`, `ENTRYPOINT`, `ENV`, `EXPOSE`, ## cp -Copy files/folders from a container's filesystem to the host -path. Paths are relative to the root of the filesystem. +Copy files/folders from a container's filesystem to the +path. Use '-' to write the data as a tar file to STDOUT. +Paths are relative to the root of the filesystem. - Usage: docker cp CONTAINER:PATH HOSTPATH + Usage: docker cp CONTAINER:PATH HOSTPATH|- + + Copy files/folders from the PATH to the HOSTPATH. Use '-' to write the data + as a tar file to STDOUT. - Copy files/folders from the PATH to the HOSTPATH ## create diff --git a/integration-cli/docker_cli_cp_test.go b/integration-cli/docker_cli_cp_test.go index ecda53526a..db5f363882 100644 --- a/integration-cli/docker_cli_cp_test.go +++ b/integration-cli/docker_cli_cp_test.go @@ -8,6 +8,7 @@ import ( "os/exec" "path" "path/filepath" + "strings" "testing" ) @@ -528,3 +529,30 @@ func TestCpToDot(t *testing.T) { } logDone("cp - to dot path") } + +func TestCpToStdout(t *testing.T) { + out, exitCode, err := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test") + if err != nil || exitCode != 0 { + t.Fatalf("failed to create a container:%s\n%s", out, err) + } + + cID := stripTrailingCharacters(out) + defer deleteContainer(cID) + + out, _, err = dockerCmd(t, "wait", cID) + if err != nil || stripTrailingCharacters(out) != "0" { + t.Fatalf("failed to set up container:%s\n%s", out, err) + } + + out, _, err = runCommandPipelineWithOutput( + exec.Command(dockerBinary, "cp", cID+":/test", "-"), + exec.Command("tar", "-vtf", "-")) + if err != nil { + t.Fatalf("Failed to run commands: %s", err) + } + + if !strings.Contains(out, "test") || !strings.Contains(out, "-rw") { + t.Fatalf("Missing file from tar TOC:\n%s", out) + } + logDone("cp - to stdout") +}