diff --git a/daemon/daemon_aufs.go b/daemon/daemon_aufs.go index 4bb553d0af..0848ea920f 100644 --- a/daemon/daemon_aufs.go +++ b/daemon/daemon_aufs.go @@ -6,7 +6,6 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/daemon/graphdriver/aufs" - "github.com/docker/docker/graph" ) // Given the graphdriver ad, if it is aufs, then migrate it. @@ -14,7 +13,7 @@ import ( func migrateIfAufs(driver graphdriver.Driver, root string) error { if ad, ok := driver.(*aufs.Driver); ok { logrus.Debugf("Migrating existing containers") - if err := ad.Migrate(root, graph.SetupInitLayer); err != nil { + if err := ad.Migrate(root, setupInitLayer); err != nil { return err } } diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 29a3c5d3dc..3a2e62106d 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -9,14 +9,15 @@ import ( "path/filepath" "runtime" "strings" + "syscall" "github.com/Sirupsen/logrus" "github.com/docker/docker/autogen/dockerversion" "github.com/docker/docker/daemon/graphdriver" - "github.com/docker/docker/graph" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/fileutils" "github.com/docker/docker/pkg/parsers/kernel" + "github.com/docker/docker/pkg/system" "github.com/docker/docker/runconfig" "github.com/docker/docker/utils" volumedrivers "github.com/docker/docker/volume/drivers" @@ -81,7 +82,7 @@ func (daemon *Daemon) createRootfs(container *Container) error { } defer daemon.driver.Put(initID) - if err := graph.SetupInitLayer(initPath); err != nil { + if err := setupInitLayer(initPath); err != nil { return err } @@ -360,3 +361,61 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error) return controller, nil } + +// 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 +} diff --git a/graph/graph.go b/graph/graph.go index 0f27e8c56a..5c5b5f0656 100644 --- a/graph/graph.go +++ b/graph/graph.go @@ -13,7 +13,6 @@ import ( "runtime" "strconv" "strings" - "syscall" "time" "github.com/Sirupsen/logrus" @@ -271,64 +270,6 @@ func bufferToFile(f *os.File, src io.Reader) (int64, digest.Digest, error) { return n, digest.NewDigest("sha256", h), nil } -// 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 -} - // Check if given error is "not empty". // Note: this is the way golang does it internally with os.IsNotExists. func isNotEmpty(err error) bool {