Use the runtime config to specify how overlay should be created

This puts the build side in charge of the runtime layout, which enables
additional optimisations later, like sharing the rootfs if it is
used multiple times.

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
This commit is contained in:
Justin Cormack 2017-08-22 16:21:56 +01:00
parent ee0901762f
commit 6b98aff58b
2 changed files with 35 additions and 25 deletions

View File

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

View File

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