|
@@ -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
|
|
|
+}
|