From 57d79e1b49c8d339028ca518fa0b89b4c5ff9ac2 Mon Sep 17 00:00:00 2001 From: Wei Fu Date: Fri, 28 Sep 2018 13:40:24 +0800 Subject: [PATCH 1/2] bugfix: cache empty layer for docker schema1 image containerd should cache empty label for docker schema1 image. if not, the original empty layer will be non-empty layer and the image config will be changed too. in this case, the image ID will be changed. check the blob empty label to avoid changing image ID when repull docker schema1 image. Signed-off-by: Wei Fu --- remotes/docker/schema1/converter.go | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/remotes/docker/schema1/converter.go b/remotes/docker/schema1/converter.go index 45ac1933f..42e32b1fb 100644 --- a/remotes/docker/schema1/converter.go +++ b/remotes/docker/schema1/converter.go @@ -24,6 +24,7 @@ import ( "fmt" "io" "io/ioutil" + "strconv" "strings" "sync" "time" @@ -42,7 +43,10 @@ import ( "github.com/pkg/errors" ) -const manifestSizeLimit = 8e6 // 8MB +const ( + manifestSizeLimit = 8e6 // 8MB + labelDockerSchema1EmptyLayer = "containerd.io/docker.schema1.empty.layer" +) type blobState struct { diffID digest.Digest @@ -353,10 +357,11 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro Digest: desc.Digest, Labels: map[string]string{ "containerd.io/uncompressed": state.diffID.String(), + labelDockerSchema1EmptyLayer: strconv.FormatBool(state.empty), }, } - if _, err := c.contentStore.Update(ctx, cinfo, "labels.containerd.io/uncompressed"); err != nil { + if _, err := c.contentStore.Update(ctx, cinfo, "labels.containerd.io/uncompressed", fmt.Sprintf("labels.%s", labelDockerSchema1EmptyLayer)); err != nil { return errors.Wrap(err, "failed to update uncompressed label") } @@ -380,7 +385,18 @@ func (c *Converter) reuseLabelBlobState(ctx context.Context, desc ocispec.Descri return false, nil } - bState := blobState{empty: false} + emptyVal, ok := cinfo.Labels[labelDockerSchema1EmptyLayer] + if !ok { + return false, nil + } + + isEmpty, err := strconv.ParseBool(emptyVal) + if err != nil { + log.G(ctx).WithField("id", desc.Digest).Warnf("failed to parse bool from label %s: %v", labelDockerSchema1EmptyLayer, isEmpty) + return false, nil + } + + bState := blobState{empty: isEmpty} if bState.diffID, err = digest.Parse(diffID); err != nil { log.G(ctx).WithField("id", desc.Digest).Warnf("failed to parse digest from label containerd.io/uncompressed: %v", diffID) From 26506e9e2367534e2b0b3f1db8d0977e199b513d Mon Sep 17 00:00:00 2001 From: Derek McGowan Date: Mon, 15 Oct 2018 11:28:45 -0700 Subject: [PATCH 2/2] Update empty layer label Signed-off-by: Derek McGowan --- remotes/docker/schema1/converter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/remotes/docker/schema1/converter.go b/remotes/docker/schema1/converter.go index 42e32b1fb..766c24a26 100644 --- a/remotes/docker/schema1/converter.go +++ b/remotes/docker/schema1/converter.go @@ -45,7 +45,7 @@ import ( const ( manifestSizeLimit = 8e6 // 8MB - labelDockerSchema1EmptyLayer = "containerd.io/docker.schema1.empty.layer" + labelDockerSchema1EmptyLayer = "containerd.io/docker.schema1.empty-layer" ) type blobState struct {