mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #25090 from swernli/rootfs-cleanup
Removing old custom RootFS behavior on Windows.
This commit is contained in:
commit
6c07fbd455
9 changed files with 25 additions and 130 deletions
|
@ -426,9 +426,8 @@ func rootFSToAPIType(rootfs *image.RootFS) types.RootFS {
|
||||||
layers = append(layers, l.String())
|
layers = append(layers, l.String())
|
||||||
}
|
}
|
||||||
return types.RootFS{
|
return types.RootFS{
|
||||||
Type: rootfs.Type,
|
Type: rootfs.Type,
|
||||||
Layers: layers,
|
Layers: layers,
|
||||||
BaseLayer: rootfs.BaseLayer,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,15 +89,10 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e
|
||||||
|
|
||||||
// s.Windows.LayerPaths
|
// s.Windows.LayerPaths
|
||||||
var layerPaths []string
|
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.
|
// 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)
|
max := len(img.RootFS.DiffIDs)
|
||||||
for i := start; i <= max; i++ {
|
for i := 1; i <= max; i++ {
|
||||||
img.RootFS.DiffIDs = img.RootFS.DiffIDs[:i]
|
img.RootFS.DiffIDs = img.RootFS.DiffIDs[:i]
|
||||||
path, err := layer.GetLayerPath(daemon.layerStore, img.RootFS.ChainID())
|
path, err := layer.GetLayerPath(daemon.layerStore, img.RootFS.ChainID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -423,10 +423,6 @@ func (p *v2Puller) pullSchema1(ctx context.Context, ref reference.Named, unverif
|
||||||
|
|
||||||
rootFS := image.NewRootFS()
|
rootFS := image.NewRootFS()
|
||||||
|
|
||||||
if err := detectBaseLayer(p.config.ImageStore, verifiedManifest, rootFS); err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove duplicate layers and check parent chain validity
|
// remove duplicate layers and check parent chain validity
|
||||||
err = fixManifestLayers(verifiedManifest)
|
err = fixManifestLayers(verifiedManifest)
|
||||||
if err != nil {
|
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
|
unmarshalledConfig image.Image // deserialized image config
|
||||||
downloadRootFS image.RootFS // rootFS to use for registering layers.
|
downloadRootFS image.RootFS // rootFS to use for registering layers.
|
||||||
)
|
)
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
configJSON, unmarshalledConfig, err = receiveConfig(configChan, errChan)
|
// https://github.com/docker/docker/issues/24766 - Err on the side of caution,
|
||||||
if err != nil {
|
// explicitly blocking images intended for linux from the Windows daemon
|
||||||
return "", "", err
|
if runtime.GOOS == "windows" && unmarshalledConfig.OS == "linux" {
|
||||||
}
|
return "", "", fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
downloadRootFS = *image.NewRootFS()
|
||||||
|
|
||||||
rootFS, release, err := p.config.DownloadManager.Download(ctx, downloadRootFS, descriptors, p.config.ProgressOutput)
|
rootFS, release, err := p.config.DownloadManager.Download(ctx, downloadRootFS, descriptors, p.config.ProgressOutput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if configJSON != nil {
|
if configJSON != nil {
|
||||||
|
|
|
@ -5,14 +5,8 @@ package distribution
|
||||||
import (
|
import (
|
||||||
"github.com/docker/distribution"
|
"github.com/docker/distribution"
|
||||||
"github.com/docker/distribution/context"
|
"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) {
|
func (ld *v2LayerDescriptor) open(ctx context.Context) (distribution.ReadSeekCloser, error) {
|
||||||
blobs := ld.repo.Blobs(ctx)
|
blobs := ld.repo.Blobs(ctx)
|
||||||
return blobs.Open(ctx, ld.digest)
|
return blobs.Open(ctx, ld.digest)
|
||||||
|
|
|
@ -3,38 +3,15 @@
|
||||||
package distribution
|
package distribution
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/docker/distribution"
|
"github.com/docker/distribution"
|
||||||
"github.com/docker/distribution/context"
|
"github.com/docker/distribution/context"
|
||||||
"github.com/docker/distribution/manifest/schema1"
|
|
||||||
"github.com/docker/distribution/manifest/schema2"
|
"github.com/docker/distribution/manifest/schema2"
|
||||||
"github.com/docker/distribution/registry/client/transport"
|
"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{}
|
var _ distribution.Describable = &v2LayerDescriptor{}
|
||||||
|
|
||||||
func (ld *v2LayerDescriptor) Descriptor() distribution.Descriptor {
|
func (ld *v2LayerDescriptor) Descriptor() distribution.Descriptor {
|
||||||
|
|
|
@ -5,6 +5,14 @@ import "github.com/docker/docker/layer"
|
||||||
// TypeLayers is used for RootFS.Type for filesystems organized into layers.
|
// TypeLayers is used for RootFS.Type for filesystems organized into layers.
|
||||||
const TypeLayers = "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
|
// NewRootFS returns empty RootFS struct
|
||||||
func NewRootFS() *RootFS {
|
func NewRootFS() *RootFS {
|
||||||
return &RootFS{Type: TypeLayers}
|
return &RootFS{Type: TypeLayers}
|
||||||
|
@ -14,3 +22,8 @@ func NewRootFS() *RootFS {
|
||||||
func (r *RootFS) Append(id layer.DiffID) {
|
func (r *RootFS) Append(id layer.DiffID) {
|
||||||
r.DiffIDs = append(r.DiffIDs, id)
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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}
|
|
||||||
}
|
|
|
@ -370,10 +370,7 @@ whitespace. It has been added to this example for clarity.
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<code>type</code> is usually set to <code>layers</code>. There is
|
<code>type</code> is usually set to <code>layers</code>.
|
||||||
also a Windows-specific value <code>layers+base</code> that allows
|
|
||||||
a base layer to be specified in a field of <code>rootfs</code>
|
|
||||||
called <code>base_layer</code>.
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<code>diff_ids</code> is an array of layer content hashes (<code>DiffIDs</code>), in order from bottom-most to top-most.
|
<code>diff_ids</code> is an array of layer content hashes (<code>DiffIDs</code>), in order from bottom-most to top-most.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue