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 }