Sfoglia il codice sorgente

docker tar: stream the contents of a container as a tar archive

Solomon Hykes 12 anni fa
parent
commit
3703536303
3 ha cambiato i file con 48 aggiunte e 2 eliminazioni
  1. 10 2
      dockerd/dockerd.go
  2. 18 0
      filesystem.go
  3. 20 0
      utils.go

+ 10 - 2
dockerd/dockerd.go

@@ -39,6 +39,7 @@ func (srv *Server) Help() string {
 		{"commit", "Save the state of a container"},
 		{"attach", "Attach to the standard inputs and outputs of a running container"},
 		{"info", "Display system-wide information"},
+		{"tar", "Stream the contents of a container as a tar archive"},
 		{"web", "Generate a web UI"},
 	} {
 		help += fmt.Sprintf("    %-10.10s%s\n", cmd...)
@@ -233,9 +234,16 @@ func (srv *Server) CmdTar(stdin io.ReadCloser, stdout io.Writer, args ...string)
 		return nil
 	}
 	name := flags.Arg(0)
-	if _, exists := srv.findContainer(name); exists {
+	if container, exists := srv.findContainer(name); exists {
+		data, err := container.Filesystem.Tar()
+		if err != nil {
+			return err
+		}
 		// Stream the entire contents of the container (basically a volatile snapshot)
-		return fake.WriteFakeTar(stdout)
+		if _, err := io.Copy(stdout, data); err != nil {
+			return err
+		}
+		return nil
 	}
 	return errors.New("No such container: " + name)
 }

+ 18 - 0
filesystem.go

@@ -67,6 +67,24 @@ func (fs *Filesystem) IsMounted() bool {
 	return false
 }
 
+// Tar returns the contents of the filesystem as an uncompressed tar stream
+func (fs *Filesystem) Tar() (io.Reader, error) {
+	if err := fs.EnsureMounted(); err != nil {
+		return nil, err
+	}
+	return Tar(fs.RootFS)
+}
+
+
+func (fs *Filesystem) EnsureMounted() error {
+	if !fs.IsMounted() {
+		if err := fs.Mount(); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
 type ChangeType int
 
 const (

+ 20 - 0
utils.go

@@ -5,8 +5,28 @@ import (
 	"container/list"
 	"io"
 	"sync"
+	"os/exec"
 )
 
+// Tar generates a tar archive from a filesystem path, and returns it as a stream.
+// Path must point to a directory.
+
+func Tar(path string) (io.Reader, error) {
+	cmd := exec.Command("tar", "-C", path, "-c", ".")
+	output, err := cmd.StdoutPipe()
+	if err != nil {
+		return nil, err
+	}
+	if err := cmd.Start(); err != nil {
+		return nil, err
+	}
+	// FIXME: errors will not be passed because we don't wait for the command.
+	// Instead, consumers will hit EOF right away.
+	// This can be fixed by waiting for the process to exit, or for the first write
+	// on stdout, whichever comes first.
+	return output, nil
+}
+
 type nopWriteCloser struct {
 	io.Writer
 }