export.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. package daemon
  2. import (
  3. "fmt"
  4. "io"
  5. "github.com/docker/docker/container"
  6. "github.com/docker/docker/pkg/archive"
  7. "github.com/docker/docker/pkg/ioutils"
  8. )
  9. // ContainerExport writes the contents of the container to the given
  10. // writer. An error is returned if the container cannot be found.
  11. func (daemon *Daemon) ContainerExport(name string, out io.Writer) error {
  12. container, err := daemon.GetContainer(name)
  13. if err != nil {
  14. return err
  15. }
  16. data, err := daemon.containerExport(container)
  17. if err != nil {
  18. return fmt.Errorf("Error exporting container %s: %v", name, err)
  19. }
  20. defer data.Close()
  21. // Stream the entire contents of the container (basically a volatile snapshot)
  22. if _, err := io.Copy(out, data); err != nil {
  23. return fmt.Errorf("Error exporting container %s: %v", name, err)
  24. }
  25. return nil
  26. }
  27. func (daemon *Daemon) containerExport(container *container.Container) (archive.Archive, error) {
  28. if err := daemon.Mount(container); err != nil {
  29. return nil, err
  30. }
  31. uidMaps, gidMaps := daemon.GetUIDGIDMaps()
  32. archive, err := archive.TarWithOptions(container.BaseFS, &archive.TarOptions{
  33. Compression: archive.Uncompressed,
  34. UIDMaps: uidMaps,
  35. GIDMaps: gidMaps,
  36. })
  37. if err != nil {
  38. daemon.Unmount(container)
  39. return nil, err
  40. }
  41. arch := ioutils.NewReadCloserWrapper(archive, func() error {
  42. err := archive.Close()
  43. daemon.Unmount(container)
  44. return err
  45. })
  46. daemon.LogContainerEvent(container, "export")
  47. return arch, err
  48. }