daemon/export.go
8031c23b
 package daemon
 
 import (
a793564b
 	"fmt"
8031c23b
 	"io"
73932d8d
 	"runtime"
0a734182
 
6bb0d181
 	"github.com/docker/docker/container"
d453fe35
 	"github.com/docker/docker/errdefs"
1c94f5f5
 	"github.com/docker/docker/pkg/archive"
 	"github.com/docker/docker/pkg/ioutils"
0cba7740
 	"github.com/docker/docker/pkg/system"
8031c23b
 )
 
abd72d40
 // ContainerExport writes the contents of the container to the given
 // writer. An error is returned if the container cannot be found.
b08f071e
 func (daemon *Daemon) ContainerExport(name string, out io.Writer) error {
d7d512bb
 	container, err := daemon.GetContainer(name)
d25a6537
 	if err != nil {
c79b9bab
 		return err
8031c23b
 	}
d25a6537
 
0380fbff
 	if runtime.GOOS == "windows" && container.OS == "windows" {
 		return fmt.Errorf("the daemon on this operating system does not support exporting Windows containers")
5459ef0e
 	}
 
8c326599
 	if container.IsDead() {
 		err := fmt.Errorf("You cannot export container %s which is Dead", container.ID)
87a12421
 		return errdefs.Conflict(err)
8c326599
 	}
 
 	if container.IsRemovalInProgress() {
 		err := fmt.Errorf("You cannot export container %s which is being removed", container.ID)
87a12421
 		return errdefs.Conflict(err)
8c326599
 	}
 
1c94f5f5
 	data, err := daemon.containerExport(container)
d25a6537
 	if err != nil {
a793564b
 		return fmt.Errorf("Error exporting container %s: %v", name, err)
d25a6537
 	}
 	defer data.Close()
 
 	// Stream the entire contents of the container (basically a volatile snapshot)
6b737752
 	if _, err := io.Copy(out, data); err != nil {
a793564b
 		return fmt.Errorf("Error exporting container %s: %v", name, err)
d25a6537
 	}
c79b9bab
 	return nil
8031c23b
 }
1c94f5f5
 
8c326599
 func (daemon *Daemon) containerExport(container *container.Container) (arch io.ReadCloser, err error) {
0cba7740
 	if !system.IsOSSupported(container.OS) {
 		return nil, fmt.Errorf("cannot export %s: %s ", container.ID, system.ErrNotSupportedOperatingSystem)
 	}
afd305c4
 	rwlayer, err := daemon.layerStores[container.OS].GetRWLayer(container.ID)
8c326599
 	if err != nil {
 		return nil, err
 	}
 	defer func() {
 		if err != nil {
afd305c4
 			daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer)
8c326599
 		}
 	}()
 
 	_, err = rwlayer.Mount(container.GetMountLabel())
 	if err != nil {
1c94f5f5
 		return nil, err
 	}
 
7a7357da
 	archive, err := archivePath(container.BaseFS, container.BaseFS.Path(), &archive.TarOptions{
1c94f5f5
 		Compression: archive.Uncompressed,
09cd96c5
 		UIDMaps:     daemon.idMappings.UIDs(),
 		GIDMaps:     daemon.idMappings.GIDs(),
1c94f5f5
 	})
 	if err != nil {
8c326599
 		rwlayer.Unmount()
1c94f5f5
 		return nil, err
 	}
8c326599
 	arch = ioutils.NewReadCloserWrapper(archive, func() error {
1c94f5f5
 		err := archive.Close()
8c326599
 		rwlayer.Unmount()
afd305c4
 		daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer)
1c94f5f5
 		return err
 	})
ca5ede2d
 	daemon.LogContainerEvent(container, "export")
1c94f5f5
 	return arch, err
 }