8031c23b |
package daemon
import ( |
a793564b |
"fmt" |
8031c23b |
"io" |
73932d8d |
"runtime" |
0a734182 |
|
6bb0d181 |
"github.com/docker/docker/container" |
d453fe35 |
"github.com/docker/docker/errdefs" |
1c94f5f5 |
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/ioutils" |
0cba7740 |
"github.com/docker/docker/pkg/system" |
8031c23b |
)
|
abd72d40 |
// ContainerExport writes the contents of the container to the given
// writer. An error is returned if the container cannot be found. |
b08f071e |
func (daemon *Daemon) ContainerExport(name string, out io.Writer) error { |
d7d512bb |
container, err := daemon.GetContainer(name) |
d25a6537 |
if err != nil { |
c79b9bab |
return err |
8031c23b |
} |
d25a6537 |
|
0380fbff |
if runtime.GOOS == "windows" && container.OS == "windows" {
return fmt.Errorf("the daemon on this operating system does not support exporting Windows containers") |
5459ef0e |
}
|
8c326599 |
if container.IsDead() {
err := fmt.Errorf("You cannot export container %s which is Dead", container.ID) |
87a12421 |
return errdefs.Conflict(err) |
8c326599 |
}
if container.IsRemovalInProgress() {
err := fmt.Errorf("You cannot export container %s which is being removed", container.ID) |
87a12421 |
return errdefs.Conflict(err) |
8c326599 |
}
|
1c94f5f5 |
data, err := daemon.containerExport(container) |
d25a6537 |
if err != nil { |
a793564b |
return fmt.Errorf("Error exporting container %s: %v", name, err) |
d25a6537 |
}
defer data.Close()
// Stream the entire contents of the container (basically a volatile snapshot) |
6b737752 |
if _, err := io.Copy(out, data); err != nil { |
a793564b |
return fmt.Errorf("Error exporting container %s: %v", name, err) |
d25a6537 |
} |
c79b9bab |
return nil |
8031c23b |
} |
1c94f5f5 |
|
8c326599 |
func (daemon *Daemon) containerExport(container *container.Container) (arch io.ReadCloser, err error) { |
0cba7740 |
if !system.IsOSSupported(container.OS) {
return nil, fmt.Errorf("cannot export %s: %s ", container.ID, system.ErrNotSupportedOperatingSystem)
} |
afd305c4 |
rwlayer, err := daemon.layerStores[container.OS].GetRWLayer(container.ID) |
8c326599 |
if err != nil {
return nil, err
}
defer func() {
if err != nil { |
afd305c4 |
daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer) |
8c326599 |
}
}()
_, err = rwlayer.Mount(container.GetMountLabel())
if err != nil { |
1c94f5f5 |
return nil, err
}
|
7a7357da |
archive, err := archivePath(container.BaseFS, container.BaseFS.Path(), &archive.TarOptions{ |
1c94f5f5 |
Compression: archive.Uncompressed, |
09cd96c5 |
UIDMaps: daemon.idMappings.UIDs(),
GIDMaps: daemon.idMappings.GIDs(), |
1c94f5f5 |
})
if err != nil { |
8c326599 |
rwlayer.Unmount() |
1c94f5f5 |
return nil, err
} |
8c326599 |
arch = ioutils.NewReadCloserWrapper(archive, func() error { |
1c94f5f5 |
err := archive.Close() |
8c326599 |
rwlayer.Unmount() |
afd305c4 |
daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer) |
1c94f5f5 |
return err
}) |
ca5ede2d |
daemon.LogContainerEvent(container, "export") |
1c94f5f5 |
return arch, err
} |