export.go 2.2 KB

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