diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go index 4222c960b8..208c79d4c7 100644 --- a/daemon/daemon_windows.go +++ b/daemon/daemon_windows.go @@ -426,9 +426,8 @@ func rootFSToAPIType(rootfs *image.RootFS) types.RootFS { layers = append(layers, l.String()) } return types.RootFS{ - Type: rootfs.Type, - Layers: layers, - BaseLayer: rootfs.BaseLayer, + Type: rootfs.Type, + Layers: layers, } } diff --git a/daemon/oci_windows.go b/daemon/oci_windows.go index 571f273917..0e004d8150 100644 --- a/daemon/oci_windows.go +++ b/daemon/oci_windows.go @@ -89,15 +89,10 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e // s.Windows.LayerPaths var layerPaths []string - if img.RootFS != nil && (img.RootFS.Type == image.TypeLayers || img.RootFS.Type == image.TypeLayersWithBase) { + if img.RootFS != nil && img.RootFS.Type == image.TypeLayers { // Get the layer path for each layer. - start := 1 - if img.RootFS.Type == image.TypeLayersWithBase { - // Include an empty slice to get the base layer ID. - start = 0 - } max := len(img.RootFS.DiffIDs) - for i := start; i <= max; i++ { + for i := 1; i <= max; i++ { img.RootFS.DiffIDs = img.RootFS.DiffIDs[:i] path, err := layer.GetLayerPath(daemon.layerStore, img.RootFS.ChainID()) if err != nil { diff --git a/distribution/pull_v2.go b/distribution/pull_v2.go index f6c353fc43..8ee6ed8aa3 100644 --- a/distribution/pull_v2.go +++ b/distribution/pull_v2.go @@ -423,10 +423,6 @@ func (p *v2Puller) pullSchema1(ctx context.Context, ref reference.Named, unverif rootFS := image.NewRootFS() - if err := detectBaseLayer(p.config.ImageStore, verifiedManifest, rootFS); err != nil { - return "", "", err - } - // remove duplicate layers and check parent chain validity err = fixManifestLayers(verifiedManifest) if err != nil { @@ -542,25 +538,15 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s unmarshalledConfig image.Image // deserialized image config downloadRootFS image.RootFS // rootFS to use for registering layers. ) - if runtime.GOOS == "windows" { - configJSON, unmarshalledConfig, err = receiveConfig(configChan, errChan) - if err != nil { - return "", "", err - } - if unmarshalledConfig.RootFS == nil { - return "", "", errors.New("image config has no rootfs section") - } - // https://github.com/docker/docker/issues/24766 - Err on the side of caution, - // explicitly blocking images intended for linux from the Windows daemon - if unmarshalledConfig.OS == "linux" { - return "", "", fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS) - } - downloadRootFS = *unmarshalledConfig.RootFS - downloadRootFS.DiffIDs = []layer.DiffID{} - } else { - downloadRootFS = *image.NewRootFS() + + // https://github.com/docker/docker/issues/24766 - Err on the side of caution, + // explicitly blocking images intended for linux from the Windows daemon + if runtime.GOOS == "windows" && unmarshalledConfig.OS == "linux" { + return "", "", fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS) } + downloadRootFS = *image.NewRootFS() + rootFS, release, err := p.config.DownloadManager.Download(ctx, downloadRootFS, descriptors, p.config.ProgressOutput) if err != nil { if configJSON != nil { diff --git a/distribution/pull_v2_unix.go b/distribution/pull_v2_unix.go index cdd7806ad2..45a7a0c150 100644 --- a/distribution/pull_v2_unix.go +++ b/distribution/pull_v2_unix.go @@ -5,14 +5,8 @@ package distribution import ( "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/manifest/schema1" - "github.com/docker/docker/image" ) -func detectBaseLayer(is image.Store, m *schema1.Manifest, rootFS *image.RootFS) error { - return nil -} - func (ld *v2LayerDescriptor) open(ctx context.Context) (distribution.ReadSeekCloser, error) { blobs := ld.repo.Blobs(ctx) return blobs.Open(ctx, ld.digest) diff --git a/distribution/pull_v2_windows.go b/distribution/pull_v2_windows.go index f98825d0be..bd0bae772e 100644 --- a/distribution/pull_v2_windows.go +++ b/distribution/pull_v2_windows.go @@ -3,38 +3,15 @@ package distribution import ( - "encoding/json" - "fmt" "net/http" "os" "github.com/docker/distribution" "github.com/docker/distribution/context" - "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" "github.com/docker/distribution/registry/client/transport" - "github.com/docker/docker/image" ) -func detectBaseLayer(is image.Store, m *schema1.Manifest, rootFS *image.RootFS) error { - v1img := &image.V1Image{} - if err := json.Unmarshal([]byte(m.History[len(m.History)-1].V1Compatibility), v1img); err != nil { - return err - } - if v1img.Parent == "" { - return fmt.Errorf("Last layer %q does not have a base layer reference", v1img.ID) - } - // There must be an image that already references the baselayer. - for _, img := range is.Map() { - if img.RootFS.Type == image.TypeLayersWithBase && img.RootFS.BaseLayerID() == v1img.Parent { - rootFS.BaseLayer = img.RootFS.BaseLayer - rootFS.Type = image.TypeLayersWithBase - return nil - } - } - return fmt.Errorf("Invalid base layer %q", v1img.Parent) -} - var _ distribution.Describable = &v2LayerDescriptor{} func (ld *v2LayerDescriptor) Descriptor() distribution.Descriptor { diff --git a/image/rootfs.go b/image/rootfs.go index 76eaae0c25..4cbb87381d 100644 --- a/image/rootfs.go +++ b/image/rootfs.go @@ -5,6 +5,14 @@ import "github.com/docker/docker/layer" // TypeLayers is used for RootFS.Type for filesystems organized into layers. const TypeLayers = "layers" +// RootFS describes images root filesystem +// This is currently a placeholder that only supports layers. In the future +// this can be made into an interface that supports different implementations. +type RootFS struct { + Type string `json:"type"` + DiffIDs []layer.DiffID `json:"diff_ids,omitempty"` +} + // NewRootFS returns empty RootFS struct func NewRootFS() *RootFS { return &RootFS{Type: TypeLayers} @@ -14,3 +22,8 @@ func NewRootFS() *RootFS { func (r *RootFS) Append(id layer.DiffID) { r.DiffIDs = append(r.DiffIDs, id) } + +// ChainID returns the ChainID for the top layer in RootFS. +func (r *RootFS) ChainID() layer.ChainID { + return layer.CreateChainID(r.DiffIDs) +} diff --git a/image/rootfs_unix.go b/image/rootfs_unix.go deleted file mode 100644 index 83498f6c37..0000000000 --- a/image/rootfs_unix.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build !windows - -package image - -import "github.com/docker/docker/layer" - -// RootFS describes images root filesystem -// This is currently a placeholder that only supports layers. In the future -// this can be made into an interface that supports different implementations. -type RootFS struct { - Type string `json:"type"` - DiffIDs []layer.DiffID `json:"diff_ids,omitempty"` -} - -// ChainID returns the ChainID for the top layer in RootFS. -func (r *RootFS) ChainID() layer.ChainID { - return layer.CreateChainID(r.DiffIDs) -} diff --git a/image/rootfs_windows.go b/image/rootfs_windows.go deleted file mode 100644 index c5bd5828b5..0000000000 --- a/image/rootfs_windows.go +++ /dev/null @@ -1,48 +0,0 @@ -// +build windows - -package image - -import ( - "crypto/sha512" - "fmt" - - "github.com/docker/distribution/digest" - "github.com/docker/docker/layer" -) - -// TypeLayersWithBase is used for RootFS.Type for Windows filesystems that have layers and a centrally-stored base layer. -const TypeLayersWithBase = "layers+base" - -// RootFS describes images root filesystem -// This is currently a placeholder that only supports layers. In the future -// this can be made into an interface that supports different implementations. -type RootFS struct { - Type string `json:"type"` - DiffIDs []layer.DiffID `json:"diff_ids,omitempty"` - BaseLayer string `json:"base_layer,omitempty"` -} - -// BaseLayerID returns the 64 byte hex ID for the baselayer name. -func (r *RootFS) BaseLayerID() string { - if r.Type != TypeLayersWithBase { - panic("tried to get base layer ID without a base layer") - } - baseID := sha512.Sum384([]byte(r.BaseLayer)) - return fmt.Sprintf("%x", baseID[:32]) -} - -// ChainID returns the ChainID for the top layer in RootFS. -func (r *RootFS) ChainID() layer.ChainID { - ids := r.DiffIDs - if r.Type == TypeLayersWithBase { - // Add an extra ID for the base. - baseDiffID := layer.DiffID(digest.FromBytes([]byte(r.BaseLayerID()))) - ids = append([]layer.DiffID{baseDiffID}, ids...) - } - return layer.CreateChainID(ids) -} - -// NewRootFSWithBaseLayer returns a RootFS struct with a base layer -func NewRootFSWithBaseLayer(baseLayer string) *RootFS { - return &RootFS{Type: TypeLayersWithBase, BaseLayer: baseLayer} -} diff --git a/image/spec/v1.1.md b/image/spec/v1.1.md index 3a32b6bd36..63e97def13 100644 --- a/image/spec/v1.1.md +++ b/image/spec/v1.1.md @@ -370,10 +370,7 @@ whitespace. It has been added to this example for clarity.
type
is usually set to layers
. There is
- also a Windows-specific value layers+base
that allows
- a base layer to be specified in a field of rootfs
- called base_layer
.
+ type
is usually set to layers
.
diff_ids
is an array of layer content hashes (DiffIDs
), in order from bottom-most to top-most.