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:
parent
b6fb5bb21b
commit
3703536303
3 changed files with 48 additions and 2 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
20
utils.go
20
utils.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue