1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

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

This commit is contained in:
Solomon Hykes 2013-01-27 00:59:49 -08:00
parent b6fb5bb21b
commit 3703536303
3 changed files with 48 additions and 2 deletions

View file

@ -39,6 +39,7 @@ func (srv *Server) Help() string {
{"commit", "Save the state of a container"}, {"commit", "Save the state of a container"},
{"attach", "Attach to the standard inputs and outputs of a running container"}, {"attach", "Attach to the standard inputs and outputs of a running container"},
{"info", "Display system-wide information"}, {"info", "Display system-wide information"},
{"tar", "Stream the contents of a container as a tar archive"},
{"web", "Generate a web UI"}, {"web", "Generate a web UI"},
} { } {
help += fmt.Sprintf(" %-10.10s%s\n", cmd...) 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 return nil
} }
name := flags.Arg(0) 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) // 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) return errors.New("No such container: " + name)
} }

View file

@ -67,6 +67,24 @@ func (fs *Filesystem) IsMounted() bool {
return false 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 type ChangeType int
const ( const (

View file

@ -5,8 +5,28 @@ import (
"container/list" "container/list"
"io" "io"
"sync" "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 { type nopWriteCloser struct {
io.Writer io.Writer
} }