Previously, Windows only supported running with a OS-managed base image.
With this change, Windows supports normal, Linux-like layered images, too.
Signed-off-by: John Starks <jostarks@microsoft.com>
| ... | ... |
@@ -373,8 +373,7 @@ func restoreCustomImage(is image.Store, ls layer.Store, rs reference.Store) erro |
| 373 | 373 |
} |
| 374 | 374 |
// layer is intentionally not released |
| 375 | 375 |
|
| 376 |
- rootFS := image.NewRootFS() |
|
| 377 |
- rootFS.BaseLayer = filepath.Base(info.Path) |
|
| 376 |
+ rootFS := image.NewRootFSWithBaseLayer(filepath.Base(info.Path)) |
|
| 378 | 377 |
|
| 379 | 378 |
// Create history for base layer |
| 380 | 379 |
config, err := json.Marshal(&image.Image{
|
| ... | ... |
@@ -5,6 +5,7 @@ import ( |
| 5 | 5 |
"syscall" |
| 6 | 6 |
|
| 7 | 7 |
"github.com/docker/docker/container" |
| 8 |
+ "github.com/docker/docker/image" |
|
| 8 | 9 |
"github.com/docker/docker/layer" |
| 9 | 10 |
"github.com/docker/docker/libcontainerd" |
| 10 | 11 |
"github.com/docker/docker/libcontainerd/windowsoci" |
| ... | ... |
@@ -88,9 +89,15 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e |
| 88 | 88 |
|
| 89 | 89 |
// s.Windows.LayerPaths |
| 90 | 90 |
var layerPaths []string |
| 91 |
- if img.RootFS != nil && img.RootFS.Type == "layers+base" {
|
|
| 91 |
+ if img.RootFS != nil && (img.RootFS.Type == image.TypeLayers || img.RootFS.Type == image.TypeLayersWithBase) {
|
|
| 92 |
+ // Get the layer path for each layer. |
|
| 93 |
+ start := 1 |
|
| 94 |
+ if img.RootFS.Type == image.TypeLayersWithBase {
|
|
| 95 |
+ // Include an empty slice to get the base layer ID. |
|
| 96 |
+ start = 0 |
|
| 97 |
+ } |
|
| 92 | 98 |
max := len(img.RootFS.DiffIDs) |
| 93 |
- for i := 0; i <= max; i++ {
|
|
| 99 |
+ for i := start; i <= max; i++ {
|
|
| 94 | 100 |
img.RootFS.DiffIDs = img.RootFS.DiffIDs[:i] |
| 95 | 101 |
path, err := layer.GetLayerPath(daemon.layerStore, img.RootFS.ChainID()) |
| 96 | 102 |
if err != nil {
|
| ... | ... |
@@ -20,8 +20,9 @@ func detectBaseLayer(is image.Store, m *schema1.Manifest, rootFS *image.RootFS) |
| 20 | 20 |
} |
| 21 | 21 |
// There must be an image that already references the baselayer. |
| 22 | 22 |
for _, img := range is.Map() {
|
| 23 |
- if img.RootFS.BaseLayerID() == v1img.Parent {
|
|
| 23 |
+ if img.RootFS.Type == image.TypeLayersWithBase && img.RootFS.BaseLayerID() == v1img.Parent {
|
|
| 24 | 24 |
rootFS.BaseLayer = img.RootFS.BaseLayer |
| 25 |
+ rootFS.Type = image.TypeLayersWithBase |
|
| 25 | 26 |
return nil |
| 26 | 27 |
} |
| 27 | 28 |
} |
| ... | ... |
@@ -2,6 +2,14 @@ package image |
| 2 | 2 |
|
| 3 | 3 |
import "github.com/docker/docker/layer" |
| 4 | 4 |
|
| 5 |
+// TypeLayers is used for RootFS.Type for filesystems organized into layers. |
|
| 6 |
+const TypeLayers = "layers" |
|
| 7 |
+ |
|
| 8 |
+// NewRootFS returns empty RootFS struct |
|
| 9 |
+func NewRootFS() *RootFS {
|
|
| 10 |
+ return &RootFS{Type: TypeLayers}
|
|
| 11 |
+} |
|
| 12 |
+ |
|
| 5 | 13 |
// Append appends a new diffID to rootfs |
| 6 | 14 |
func (r *RootFS) Append(id layer.DiffID) {
|
| 7 | 15 |
r.DiffIDs = append(r.DiffIDs, id) |
| ... | ... |
@@ -10,6 +10,9 @@ import ( |
| 10 | 10 |
"github.com/docker/docker/layer" |
| 11 | 11 |
) |
| 12 | 12 |
|
| 13 |
+// TypeLayersWithBase is used for RootFS.Type for Windows filesystems that have layers and a centrally-stored base layer. |
|
| 14 |
+const TypeLayersWithBase = "layers+base" |
|
| 15 |
+ |
|
| 13 | 16 |
// RootFS describes images root filesystem |
| 14 | 17 |
// This is currently a placeholder that only supports layers. In the future |
| 15 | 18 |
// this can be made into an interface that supports different implementations. |
| ... | ... |
@@ -21,17 +24,25 @@ type RootFS struct {
|
| 21 | 21 |
|
| 22 | 22 |
// BaseLayerID returns the 64 byte hex ID for the baselayer name. |
| 23 | 23 |
func (r *RootFS) BaseLayerID() string {
|
| 24 |
+ if r.Type != TypeLayersWithBase {
|
|
| 25 |
+ panic("tried to get base layer ID without a base layer")
|
|
| 26 |
+ } |
|
| 24 | 27 |
baseID := sha512.Sum384([]byte(r.BaseLayer)) |
| 25 | 28 |
return fmt.Sprintf("%x", baseID[:32])
|
| 26 | 29 |
} |
| 27 | 30 |
|
| 28 | 31 |
// ChainID returns the ChainID for the top layer in RootFS. |
| 29 | 32 |
func (r *RootFS) ChainID() layer.ChainID {
|
| 30 |
- baseDiffID := digest.FromBytes([]byte(r.BaseLayerID())) |
|
| 31 |
- return layer.CreateChainID(append([]layer.DiffID{layer.DiffID(baseDiffID)}, r.DiffIDs...))
|
|
| 33 |
+ ids := r.DiffIDs |
|
| 34 |
+ if r.Type == TypeLayersWithBase {
|
|
| 35 |
+ // Add an extra ID for the base. |
|
| 36 |
+ baseDiffID := layer.DiffID(digest.FromBytes([]byte(r.BaseLayerID()))) |
|
| 37 |
+ ids = append([]layer.DiffID{baseDiffID}, ids...)
|
|
| 38 |
+ } |
|
| 39 |
+ return layer.CreateChainID(ids) |
|
| 32 | 40 |
} |
| 33 | 41 |
|
| 34 |
-// NewRootFS returns empty RootFS struct |
|
| 35 |
-func NewRootFS() *RootFS {
|
|
| 36 |
- return &RootFS{Type: "layers+base"}
|
|
| 42 |
+// NewRootFSWithBaseLayer returns a RootFS struct with a base layer |
|
| 43 |
+func NewRootFSWithBaseLayer(baseLayer string) *RootFS {
|
|
| 44 |
+ return &RootFS{Type: TypeLayersWithBase, BaseLayer: baseLayer}
|
|
| 37 | 45 |
} |