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 }