diff --git a/src/moby/build.go b/src/moby/build.go index f98d01e75..9ce628bd3 100644 --- a/src/moby/build.go +++ b/src/moby/build.go @@ -131,13 +131,9 @@ func outputImage(image Image, section string, prefix string, m Moby, idMap map[s if err != nil { return fmt.Errorf("Failed to create config for %s: %v", image.Image, err) } - runtimeConfig, err := json.MarshalIndent(runtime, "", " ") - if err != nil { - return fmt.Errorf("Failed to create runtime config for %s: %v", image.Image, err) - } path := path.Join("containers", section, prefix+image.Name) readonly := oci.Root.Readonly - err = ImageBundle(path, image.Image, config, runtimeConfig, iw, useTrust, pull, readonly) + err = ImageBundle(path, image.Image, config, runtime, iw, useTrust, pull, readonly) if err != nil { return fmt.Errorf("Failed to extract root filesystem for %s: %v", image.Image, err) } diff --git a/src/moby/image.go b/src/moby/image.go index ce5706c8e..4d7fb3e8c 100644 --- a/src/moby/image.go +++ b/src/moby/image.go @@ -3,6 +3,7 @@ package moby import ( "archive/tar" "bytes" + "encoding/json" "fmt" "io" "io/ioutil" @@ -10,6 +11,7 @@ import ( "strings" log "github.com/Sirupsen/logrus" + "github.com/opencontainers/runtime-spec/specs-go" ) type tarWriter interface { @@ -189,9 +191,7 @@ func ImageTar(image, prefix string, tw tarWriter, trust bool, pull bool, resolv } // ImageBundle produces an OCI bundle at the given path in a tarball, given an image and a config.json -func ImageBundle(prefix string, image string, config []byte, runtimeConfig []byte, tw tarWriter, trust bool, pull bool, readonly bool) error { - log.Debugf("image bundle: %s %s cfg: %s runtime: %s", prefix, image, string(config), string(runtimeConfig)) - +func ImageBundle(prefix string, image string, config []byte, runtime Runtime, tw tarWriter, trust bool, pull bool, readonly bool) error { // if read only, just unpack in rootfs/ but otherwise set up for overlay rootfs := "rootfs" if !readonly { @@ -214,26 +214,11 @@ func ImageBundle(prefix string, image string, config []byte, runtimeConfig []byt return err } - // do not write an empty runtime config - if string(runtimeConfig) != "{}" { - hdr = &tar.Header{ - Name: path.Join(prefix, "runtime.json"), - Mode: 0644, - Size: int64(len(runtimeConfig)), - } - if err := tw.WriteHeader(hdr); err != nil { - return err - } - buf = bytes.NewBuffer(runtimeConfig) - if _, err := io.Copy(tw, buf); err != nil { - return err - } - } - if !readonly { // add a tmp directory to be used as a mount point for tmpfs for upper, work + tmp := path.Join(prefix, "tmp") hdr = &tar.Header{ - Name: path.Join(prefix, "tmp"), + Name: tmp, Mode: 0755, Typeflag: tar.TypeDir, } @@ -249,7 +234,36 @@ func ImageBundle(prefix string, image string, config []byte, runtimeConfig []byt if err := tw.WriteHeader(hdr); err != nil { return err } + runtime.Mounts = append(runtime.Mounts, specs.Mount{Source: "tmpfs", Type: "tmpfs", Destination: "/" + tmp}) + // remount private as nothing else should see the temporary layers + runtime.Mounts = append(runtime.Mounts, specs.Mount{Destination: "/" + tmp, Options: []string{"remount", "private"}}) + overlayOptions := []string{"lowerdir=/" + path.Join(prefix, "lower"), "upperdir=/" + path.Join(tmp, "upper"), "workdir=/" + path.Join(tmp, "work")} + runtime.Mounts = append(runtime.Mounts, specs.Mount{Source: "overlay", Type: "overlay", Destination: "/" + path.Join(prefix, "rootfs"), Options: overlayOptions}) + } else { + // make rootfs a mountpoint as runc can be picky about this + runtime.Mounts = append(runtime.Mounts, specs.Mount{Source: path.Join(prefix, rootfs), Destination: "/" + path.Join(prefix, "rootfs"), Options: []string{"bind"}}) } + // write the runtime config + runtimeConfig, err := json.MarshalIndent(runtime, "", " ") + if err != nil { + return fmt.Errorf("Failed to create runtime config for %s: %v", image, err) + } + + hdr = &tar.Header{ + Name: path.Join(prefix, "runtime.json"), + Mode: 0644, + Size: int64(len(runtimeConfig)), + } + if err := tw.WriteHeader(hdr); err != nil { + return err + } + buf = bytes.NewBuffer(runtimeConfig) + if _, err := io.Copy(tw, buf); err != nil { + return err + } + + log.Debugf("image bundle: %s %s cfg: %s runtime: %s", prefix, image, string(config), string(runtimeConfig)) + return nil }