export.go 2.2 KB

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