github.com/rhatdan/docker@v0.7.7-0.20180119204836-47a0dcbcd20a/daemon/export.go (about)

     1  package daemon
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"runtime"
     7  
     8  	"github.com/docker/docker/container"
     9  	"github.com/docker/docker/errdefs"
    10  	"github.com/docker/docker/pkg/archive"
    11  	"github.com/docker/docker/pkg/ioutils"
    12  	"github.com/docker/docker/pkg/system"
    13  )
    14  
    15  // ContainerExport writes the contents of the container to the given
    16  // writer. An error is returned if the container cannot be found.
    17  func (daemon *Daemon) ContainerExport(name string, out io.Writer) error {
    18  	container, err := daemon.GetContainer(name)
    19  	if err != nil {
    20  		return err
    21  	}
    22  
    23  	if runtime.GOOS == "windows" && container.OS == "windows" {
    24  		return fmt.Errorf("the daemon on this operating system does not support exporting Windows containers")
    25  	}
    26  
    27  	if container.IsDead() {
    28  		err := fmt.Errorf("You cannot export container %s which is Dead", container.ID)
    29  		return errdefs.Conflict(err)
    30  	}
    31  
    32  	if container.IsRemovalInProgress() {
    33  		err := fmt.Errorf("You cannot export container %s which is being removed", container.ID)
    34  		return errdefs.Conflict(err)
    35  	}
    36  
    37  	data, err := daemon.containerExport(container)
    38  	if err != nil {
    39  		return fmt.Errorf("Error exporting container %s: %v", name, err)
    40  	}
    41  	defer data.Close()
    42  
    43  	// Stream the entire contents of the container (basically a volatile snapshot)
    44  	if _, err := io.Copy(out, data); err != nil {
    45  		return fmt.Errorf("Error exporting container %s: %v", name, err)
    46  	}
    47  	return nil
    48  }
    49  
    50  func (daemon *Daemon) containerExport(container *container.Container) (arch io.ReadCloser, err error) {
    51  	if !system.IsOSSupported(container.OS) {
    52  		return nil, fmt.Errorf("cannot export %s: %s ", container.ID, system.ErrNotSupportedOperatingSystem)
    53  	}
    54  	rwlayer, err := daemon.layerStores[container.OS].GetRWLayer(container.ID)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	defer func() {
    59  		if err != nil {
    60  			daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer)
    61  		}
    62  	}()
    63  
    64  	_, err = rwlayer.Mount(container.GetMountLabel())
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  
    69  	archive, err := archivePath(container.BaseFS, container.BaseFS.Path(), &archive.TarOptions{
    70  		Compression: archive.Uncompressed,
    71  		UIDMaps:     daemon.idMappings.UIDs(),
    72  		GIDMaps:     daemon.idMappings.GIDs(),
    73  	})
    74  	if err != nil {
    75  		rwlayer.Unmount()
    76  		return nil, err
    77  	}
    78  	arch = ioutils.NewReadCloserWrapper(archive, func() error {
    79  		err := archive.Close()
    80  		rwlayer.Unmount()
    81  		daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer)
    82  		return err
    83  	})
    84  	daemon.LogContainerEvent(container, "export")
    85  	return arch, err
    86  }