Skip to content

Commit

Permalink
disable pulling legacy image formats by default
Browse files Browse the repository at this point in the history
This patch disables pulling legacy (schema1 and schema 2, version 1) images by
default.

A `DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE` environment-variable is
introduced to allow re-enabling this feature, aligning with the environment
variable used in containerd 2.0 (`CONTAINERD_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE`).

With this patch, attempts to pull a legacy image produces an error:

With graphdrivers:

    docker pull docker:1.0
    1.0: Pulling from library/docker
    [DEPRECATION NOTICE] Docker Image Format v1, and Docker Image manifest version 2, schema 1 support will be removed in an upcoming release. Suggest the author of docker.io/library/docker:1.0 to upgrade the image to the OCI Format, or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/

With the containerd image store enabled, output is slightly different
as it returns the error before printing the `1.0: pulling ...`:

    docker pull docker:1.0
    Error response from daemon: [DEPRECATION NOTICE] Docker Image Format v1 and Docker Image manifest version 2, schema 1 support is disabled by default and will be removed in an upcoming release. Suggest the author of docker.io/library/docker:1.0 to upgrade the image to the OCI Format or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/

Using the "distribution" endpoint to resolve the digest for an image also
produces an error:

    curl -v --unix-socket /var/run/docker.sock http://foo/distribution/docker.io/library/docker:1.0/json
    *   Trying /var/run/docker.sock:0...
    * Connected to foo (/var/run/docker.sock) port 80 (#0)
    > GET /distribution/docker.io/library/docker:1.0/json HTTP/1.1
    > Host: foo
    > User-Agent: curl/7.88.1
    > Accept: */*
    >
    < HTTP/1.1 400 Bad Request
    < Api-Version: 1.45
    < Content-Type: application/json
    < Docker-Experimental: false
    < Ostype: linux
    < Server: Docker/dev (linux)
    < Date: Tue, 27 Feb 2024 16:09:42 GMT
    < Content-Length: 354
    <
    {"message":"[DEPRECATION NOTICE] Docker Image Format v1, and Docker Image manifest version 2, schema 1 support will be removed in an upcoming release. Suggest the author of docker.io/library/docker:1.0 to upgrade the image to the OCI Format, or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/"}
    * Connection #0 to host foo left intact

Starting the daemon with the `DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE`
env-var set to a non-empty value allows pulling the image;

    docker pull docker:1.0
    [DEPRECATION NOTICE] Docker Image Format v1 and Docker Image manifest version 2, schema 1 support is disabled by default and will be removed in an upcoming release. Suggest the author of docker.io/library/docker:1.0 to upgrade the image to the OCI Format or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/
    b0a0e6710d13: Already exists
    d193ad713811: Already exists
    ba7268c3149b: Already exists
    c862d82a67a2: Already exists
    Digest: sha256:5e7081837926c7a40e58881bbebc52044a95a62a2ea52fb240db3fc539212fe5
    Status: Image is up to date for docker:1.0
    docker.io/library/docker:1.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
  • Loading branch information
thaJeztah committed Feb 27, 2024
1 parent 2208351 commit 9a9e5e5
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 2 deletions.
5 changes: 5 additions & 0 deletions api/server/router/distribution/distribution_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"net/http"
"os"

"github.com/distribution/reference"
"github.com/docker/distribution"
Expand All @@ -12,6 +13,7 @@ import (
"github.com/docker/distribution/manifest/schema2"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/api/types/registry"
distributionpkg "github.com/docker/docker/distribution"
"github.com/docker/docker/errdefs"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
Expand Down Expand Up @@ -153,6 +155,9 @@ func (s *distributionRouter) fetchManifest(ctx context.Context, distrepo distrib
}
}
case *schema1.SignedManifest:
if os.Getenv("DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE") == "" {
return registry.DistributionInspect{}, errdefs.InvalidParameter(errors.New(distributionpkg.DeprecatedSchema1ImageMessage(namedRef)))
}
platform := ocispec.Platform{
Architecture: mnfstObj.Architecture,
OS: "linux",
Expand Down
8 changes: 7 additions & 1 deletion daemon/containerd/image_pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"os"
"strings"

"github.com/containerd/containerd"
Expand Down Expand Up @@ -115,7 +116,12 @@ func (i *ImageService) pullTag(ctx context.Context, ref reference.Named, platfor
var sentPullingFrom, sentSchema1Deprecation bool
ah := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
if desc.MediaType == images.MediaTypeDockerSchema1Manifest && !sentSchema1Deprecation {
progress.Message(out, "", distribution.DeprecatedSchema1ImageMessage(ref))
msg := distribution.DeprecatedSchema1ImageMessage(ref)
if os.Getenv("DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE") == "" {
log.G(context.TODO()).Warn(msg)
return nil, errdefs.InvalidParameter(errors.New(msg))
}
progress.Message(out, "", msg)
sentSchema1Deprecation = true
}
if images.IsLayerType(desc.MediaType) {
Expand Down
8 changes: 7 additions & 1 deletion distribution/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ func (e reservedNameError) Error() string {

func (e reservedNameError) Forbidden() {}

const deprecatedSchema1 = "[DEPRECATION NOTICE] Docker Image Format v1 and Docker Image manifest version 2, schema 1 support is disabled by default and will be removed in an upcoming release. More information at https://docs.docker.com/go/deprecated-image-specs/"

type invalidArgumentErr struct{ error }

func (invalidArgumentErr) InvalidParameter() {}

func DeprecatedSchema1ImageMessage(ref reference.Named) string {
return fmt.Sprintf("[DEPRECATION NOTICE] Docker Image Format v1, and Docker Image manifest version 2, schema 1 support will be removed in an upcoming release. Suggest the author of %s to upgrade the image to the OCI Format, or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/", ref)
return fmt.Sprintf("[DEPRECATION NOTICE] Docker Image Format v1 and Docker Image manifest version 2, schema 1 support is disabled by default and will be removed in an upcoming release. Suggest the author of %s to upgrade the image to the OCI Format or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/", ref)
}
9 changes: 9 additions & 0 deletions distribution/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"io"
"os"
"strings"

"github.com/containerd/containerd/content"
Expand Down Expand Up @@ -292,6 +293,10 @@ func detectManifestBlobMediaType(dt []byte) (string, error) {
}
return mfst.MediaType, nil
case schema1.MediaTypeManifest:
if os.Getenv("DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE") == "" {
log.G(context.TODO()).Warn(deprecatedSchema1)
return "", invalidArgumentErr{errors.New(deprecatedSchema1)}
}
if mfst.Manifests != nil || mfst.Layers != nil {
return "", fmt.Errorf(`media-type: %q should not have "manifests" or "layers"`, mfst.MediaType)
}
Expand All @@ -303,6 +308,10 @@ func detectManifestBlobMediaType(dt []byte) (string, error) {
}
switch {
case mfst.FSLayers != nil && mfst.Manifests == nil && mfst.Layers == nil && mfst.Config == nil:
if os.Getenv("DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE") == "" {
log.G(context.TODO()).Warn(deprecatedSchema1)
return "", invalidArgumentErr{errors.New(deprecatedSchema1)}
}
return schema1.MediaTypeManifest, nil
case mfst.Config != nil && mfst.Manifests == nil && mfst.FSLayers == nil,
mfst.Layers != nil && mfst.Manifests == nil && mfst.FSLayers == nil:
Expand Down
6 changes: 6 additions & 0 deletions distribution/pull_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,9 @@ func (p *puller) pullTag(ctx context.Context, ref reference.Named, platform *oci
case *schema1.SignedManifest:
msg := DeprecatedSchema1ImageMessage(ref)
log.G(ctx).Warn(msg)
if os.Getenv("DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE") == "" {
return false, invalidArgumentErr{errors.New(msg)}
}
progress.Message(p.config.ProgressOutput, "", msg)

id, manifestDigest, err = p.pullSchema1(ctx, ref, v, platform)
Expand Down Expand Up @@ -859,6 +862,9 @@ func (p *puller) pullManifestList(ctx context.Context, ref reference.Named, mfst
case *schema1.SignedManifest:
msg := DeprecatedSchema1ImageMessage(ref)
log.G(ctx).Warn(msg)
if os.Getenv("DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE") == "" {
return "", "", invalidArgumentErr{errors.New(msg)}
}
progress.Message(p.config.ProgressOutput, "", msg)

platform := toOCIPlatform(match.Platform)
Expand Down
3 changes: 3 additions & 0 deletions hack/make/.integration-daemon-start
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ export DOCKER_ALLOW_SCHEMA1_PUSH_DONOTUSE=1
export DOCKER_GRAPHDRIVER=${DOCKER_GRAPHDRIVER:-vfs}
export DOCKER_USERLANDPROXY=${DOCKER_USERLANDPROXY:-true}

# Allow testing push/pull of legacy image formats
export DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE=1

# example usage: DOCKER_STORAGE_OPTS="dm.basesize=20G,dm.loopdatasize=200G"
storage_params=""
if [ -n "$DOCKER_STORAGE_OPTS" ]; then
Expand Down

0 comments on commit 9a9e5e5

Please sign in to comment.