// +build !windows package graph import ( "io/ioutil" "os" "path/filepath" "strings" "syscall" "github.com/Sirupsen/logrus" "github.com/docker/docker/image" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/system" ) // setupInitLayer populates a directory with mountpoints suitable // for bind-mounting dockerinit into the container. The mountpoint is simply an // empty file at /.dockerinit // // This extra layer is used by all containers as the top-most ro layer. It protects // the container from unwanted side-effects on the rw layer. func SetupInitLayer(initLayer string) error { for pth, typ := range map[string]string{ "/dev/pts": "dir", "/dev/shm": "dir", "/proc": "dir", "/sys": "dir", "/.dockerinit": "file", "/.dockerenv": "file", "/etc/resolv.conf": "file", "/etc/hosts": "file", "/etc/hostname": "file", "/dev/console": "file", "/etc/mtab": "/proc/mounts", } { parts := strings.Split(pth, "/") prev := "/" for _, p := range parts[1:] { prev = filepath.Join(prev, p) syscall.Unlink(filepath.Join(initLayer, prev)) } if _, err := os.Stat(filepath.Join(initLayer, pth)); err != nil { if os.IsNotExist(err) { if err := system.MkdirAll(filepath.Join(initLayer, filepath.Dir(pth)), 0755); err != nil { return err } switch typ { case "dir": if err := system.MkdirAll(filepath.Join(initLayer, pth), 0755); err != nil { return err } case "file": f, err := os.OpenFile(filepath.Join(initLayer, pth), os.O_CREATE, 0755) if err != nil { return err } f.Close() default: if err := os.Symlink(typ, filepath.Join(initLayer, pth)); err != nil { return err } } } else { return err } } } // Layer is ready to use, if it wasn't before. return nil } func (graph *Graph) restoreBaseImages() ([]string, error) { return nil, nil } // storeImage stores file system layer data for the given image to the // graph's storage driver. Image metadata is stored in a file // at the specified root directory. func (graph *Graph) storeImage(id, parent string, config []byte, layerData archive.ArchiveReader, root string) (err error) { var size int64 // Store the layer. If layerData is not nil, unpack it into the new layer if layerData != nil { if size, err = graph.disassembleAndApplyTarLayer(id, parent, layerData, root); err != nil { return err } } if err := graph.saveSize(root, int(size)); err != nil { return err } if err := ioutil.WriteFile(jsonPath(root), config, 0600); err != nil { return err } // If image is pointing to a parent via CompatibilityID write the reference to disk img, err := image.NewImgJSON(config) if err != nil { return err } if img.ParentID.Validate() == nil && parent != img.ParentID.Hex() { if err := ioutil.WriteFile(filepath.Join(root, parentFileName), []byte(parent), 0600); err != nil { return err } } return nil } // TarLayer returns a tar archive of the image's filesystem layer. func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) { rdr, err := graph.assembleTarLayer(img) if err != nil { logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID) return graph.driver.Diff(img.ID, img.Parent) } return rdr, nil }