github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/daemon/export.go (about)

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