Sfoglia il codice sorgente

Merge pull request #1267 from sridatta/new-clean-init

* Runtime: Fix to "Inject dockerinit at /.dockerinit"
Guillaume J. Charmes 12 anni fa
parent
commit
f6fa353dd8
6 ha cambiato i file con 50 aggiunte e 5 eliminazioni
  1. 1 1
      container.go
  2. 1 1
      docker/docker.go
  3. 32 1
      graph.go
  4. 14 0
      image.go
  5. 1 1
      lxc_template.go
  6. 1 1
      runtime_test.go

+ 1 - 1
container.go

@@ -631,7 +631,7 @@ func (container *Container) Start(hostConfig *HostConfig) error {
 		"-n", container.ID,
 		"-f", container.lxcConfigPath(),
 		"--",
-		"/sbin/init",
+		"/.dockerinit",
 	}
 
 	// Networking

+ 1 - 1
docker/docker.go

@@ -19,7 +19,7 @@ var (
 )
 
 func main() {
-	if utils.SelfPath() == "/sbin/init" {
+	if selfPath := utils.SelfPath(); selfPath == "/sbin/init" || selfPath == "/.dockerinit" {
 		// Running in init mode
 		docker.SysInit()
 		return

+ 32 - 1
graph.go

@@ -177,8 +177,39 @@ func (graph *Graph) Mktemp(id string) (string, error) {
 	return tmp.imageRoot(id), nil
 }
 
+// getDockerInitLayer returns the path of a layer containing a mountpoint 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 (graph *Graph) getDockerInitLayer() (string, error) {
+	tmp, err := graph.tmp()
+	if err != nil {
+		return "", err
+	}
+	initLayer := tmp.imageRoot("_dockerinit")
+	if err := os.Mkdir(initLayer, 0755); err != nil && !os.IsExist(err) {
+		// If directory already existed, keep going.
+		// For all other errors, abort.
+		return "", err
+	}
+	// FIXME: how the hell do I break down this line in a way
+	// that is idiomatic and not ugly as hell?
+	if f, err := os.OpenFile(path.Join(initLayer, ".dockerinit"), os.O_CREATE|os.O_TRUNC, 0700); err != nil && !os.IsExist(err) {
+		// If file already existed, keep going.
+		// For all other errors, abort.
+		return "", err
+	} else {
+		f.Close()
+	}
+	// Layer is ready to use, if it wasn't before.
+	return initLayer, nil
+}
+
 func (graph *Graph) tmp() (*Graph, error) {
-	return NewGraph(path.Join(graph.Root, ":tmp:"))
+	// Changed to _tmp from :tmp:, because it messed with ":" separators in aufs branch syntax...
+	return NewGraph(path.Join(graph.Root, "_tmp"))
 }
 
 // Check if given error is "not empty".

+ 14 - 0
image.go

@@ -263,6 +263,13 @@ func (img *Image) layers() ([]string, error) {
 	if len(list) == 0 {
 		return nil, fmt.Errorf("No layer found for image %s\n", img.ID)
 	}
+
+	// Inject the dockerinit layer (empty place-holder for mount-binding dockerinit)
+	if dockerinitLayer, err := img.getDockerInitLayer(); err != nil {
+		return nil, err
+	} else {
+		list = append([]string{dockerinitLayer}, list...)
+	}
 	return list, nil
 }
 
@@ -292,6 +299,13 @@ func (img *Image) GetParent() (*Image, error) {
 	return img.graph.Get(img.Parent)
 }
 
+func (img *Image) getDockerInitLayer() (string, error) {
+	if img.graph == nil {
+		return "", fmt.Errorf("Can't lookup dockerinit layer of unregistered image")
+	}
+	return img.graph.getDockerInitLayer()
+}
+
 func (img *Image) root() (string, error) {
 	if img.graph == nil {
 		return "", fmt.Errorf("Can't lookup root of unregistered image")

+ 1 - 1
lxc_template.go

@@ -84,7 +84,7 @@ lxc.mount.entry = devpts {{$ROOTFS}}/dev/pts devpts newinstance,ptmxmode=0666,no
 #lxc.mount.entry = shm {{$ROOTFS}}/dev/shm tmpfs size=65536k,nosuid,nodev,noexec 0 0
 
 # Inject docker-init
-lxc.mount.entry = {{.SysInitPath}} {{$ROOTFS}}/sbin/init none bind,ro 0 0
+lxc.mount.entry = {{.SysInitPath}} {{$ROOTFS}}/.dockerinit none bind,ro 0 0
 
 # In order to get a working DNS environment, mount bind (ro) the host's /etc/resolv.conf into the container
 lxc.mount.entry = {{.ResolvConfPath}} {{$ROOTFS}}/etc/resolv.conf none bind,ro 0 0

+ 1 - 1
runtime_test.go

@@ -73,7 +73,7 @@ func layerArchive(tarfile string) (io.Reader, error) {
 
 func init() {
 	// Hack to run sys init during unit testing
-	if utils.SelfPath() == "/sbin/init" {
+	if selfPath := utils.SelfPath(); selfPath == "/sbin/init" || selfPath == "/.dockerinit" {
 		SysInit()
 		return
 	}