graph_unix.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // +build !windows
  2. package graph
  3. import (
  4. "compress/gzip"
  5. "encoding/json"
  6. "fmt"
  7. "os"
  8. "path/filepath"
  9. "strings"
  10. "syscall"
  11. "github.com/docker/docker/image"
  12. "github.com/docker/docker/pkg/archive"
  13. "github.com/docker/docker/pkg/system"
  14. )
  15. // setupInitLayer populates a directory with mountpoints suitable
  16. // for bind-mounting dockerinit into the container. The mountpoint is simply an
  17. // empty file at /.dockerinit
  18. //
  19. // This extra layer is used by all containers as the top-most ro layer. It protects
  20. // the container from unwanted side-effects on the rw layer.
  21. func SetupInitLayer(initLayer string) error {
  22. for pth, typ := range map[string]string{
  23. "/dev/pts": "dir",
  24. "/dev/shm": "dir",
  25. "/proc": "dir",
  26. "/sys": "dir",
  27. "/.dockerinit": "file",
  28. "/.dockerenv": "file",
  29. "/etc/resolv.conf": "file",
  30. "/etc/hosts": "file",
  31. "/etc/hostname": "file",
  32. "/dev/console": "file",
  33. "/etc/mtab": "/proc/mounts",
  34. } {
  35. parts := strings.Split(pth, "/")
  36. prev := "/"
  37. for _, p := range parts[1:] {
  38. prev = filepath.Join(prev, p)
  39. syscall.Unlink(filepath.Join(initLayer, prev))
  40. }
  41. if _, err := os.Stat(filepath.Join(initLayer, pth)); err != nil {
  42. if os.IsNotExist(err) {
  43. if err := system.MkdirAll(filepath.Join(initLayer, filepath.Dir(pth)), 0755); err != nil {
  44. return err
  45. }
  46. switch typ {
  47. case "dir":
  48. if err := system.MkdirAll(filepath.Join(initLayer, pth), 0755); err != nil {
  49. return err
  50. }
  51. case "file":
  52. f, err := os.OpenFile(filepath.Join(initLayer, pth), os.O_CREATE, 0755)
  53. if err != nil {
  54. return err
  55. }
  56. f.Close()
  57. default:
  58. if err := os.Symlink(typ, filepath.Join(initLayer, pth)); err != nil {
  59. return err
  60. }
  61. }
  62. } else {
  63. return err
  64. }
  65. }
  66. }
  67. // Layer is ready to use, if it wasn't before.
  68. return nil
  69. }
  70. func createRootFilesystemInDriver(graph *Graph, img *image.Image, layerData archive.ArchiveReader) error {
  71. if err := graph.driver.Create(img.ID, img.Parent); err != nil {
  72. return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, img.ID, err)
  73. }
  74. return nil
  75. }
  76. func (graph *Graph) restoreBaseImages() ([]string, error) {
  77. return nil, nil
  78. }
  79. // storeImage stores file system layer data for the given image to the
  80. // graph's storage driver. Image metadata is stored in a file
  81. // at the specified root directory.
  82. func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) {
  83. // Store the layer. If layerData is not nil, unpack it into the new layer
  84. if layerData != nil {
  85. // this is saving the tar-split metadata
  86. mf, err := os.OpenFile(filepath.Join(root, tardataFileName), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
  87. if err != nil {
  88. return err
  89. }
  90. defer mf.Close()
  91. mfz := gzip.NewWriter(mf)
  92. defer mfz.Close()
  93. metaPacker := storage.NewJSONPacker(mf)
  94. inflatedLayerData, err := archive.DecompressStream(layerData)
  95. if err != nil {
  96. return err
  97. }
  98. // we're passing nil here for the file putter, because the ApplyDiff will
  99. // handle the extraction of the archive
  100. its, err := asm.NewInputTarStream(inflatedLayerData, metaPacker, nil)
  101. if err != nil {
  102. return err
  103. }
  104. if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, archive.ArchiveReader(its)); err != nil {
  105. return err
  106. }
  107. }
  108. if err := graph.saveSize(root, int(img.Size)); err != nil {
  109. return err
  110. }
  111. f, err := os.OpenFile(jsonPath(root), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
  112. if err != nil {
  113. return err
  114. }
  115. defer f.Close()
  116. return json.NewEncoder(f).Encode(img)
  117. }
  118. // TarLayer returns a tar archive of the image's filesystem layer.
  119. func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) {
  120. // TODO(vbatts) let's reassemble!
  121. return graph.driver.Diff(img.ID, img.Parent)
  122. }