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