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