| //go:build linux || freebsd | |
| package initlayer // import "github.com/docker/docker/daemon/initlayer" | |
| import ( | |
| "os" | |
| "path/filepath" | |
| "strings" | |
| "github.com/docker/docker/pkg/idtools" | |
| "golang.org/x/sys/unix" | |
| ) | |
| // Setup populates a directory with mountpoints suitable | |
| // for bind-mounting things into the container. | |
| // | |
| // 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 Setup(initLayerFs string, rootIdentity idtools.Identity) error { | |
| // Since all paths are local to the container, we can just extract initLayerFs.Path() | |
| initLayer := initLayerFs | |
| for pth, typ := range map[string]string{ | |
| "/dev/pts": "dir", | |
| "/dev/shm": "dir", | |
| "/proc": "dir", | |
| "/sys": "dir", | |
| "/.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) | |
| unix.Unlink(filepath.Join(initLayer, prev)) | |
| } | |
| if _, err := os.Stat(filepath.Join(initLayer, pth)); err != nil { | |
| if os.IsNotExist(err) { | |
| if err := idtools.MkdirAllAndChownNew(filepath.Join(initLayer, filepath.Dir(pth)), 0o755, rootIdentity); err != nil { | |
| return err | |
| } | |
| switch typ { | |
| case "dir": | |
| if err := idtools.MkdirAllAndChownNew(filepath.Join(initLayer, pth), 0o755, rootIdentity); err != nil { | |
| return err | |
| } | |
| case "file": | |
| f, err := os.OpenFile(filepath.Join(initLayer, pth), os.O_CREATE, 0o755) | |
| if err != nil { | |
| return err | |
| } | |
| f.Chown(rootIdentity.UID, rootIdentity.GID) | |
| 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 | |
| } |