Skip to content

Commit bac85b8

Browse files
committed
Remove the support for Schema 1 images
Schema 1 (`application/vnd.docker.distribution.manifest.v1+prettyjws`) has been officially deprecated since containerd v1.7 (PR 6884). Users who have been seeing warnings like `conversion from schema 1 images is deprecated` now have to rebuild the image with Schema 2 or OCI. Schema 2 was introduced in Docker 1.10 (Feb 2016), so most users should have been already using Schema 2 or OCI. Signed-off-by: Akihiro Suda <[email protected]>
1 parent c78d526 commit bac85b8

17 files changed

Lines changed: 70 additions & 848 deletions

File tree

RELEASES.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -396,17 +396,17 @@ against total impact.
396396

397397
The deprecated features are shown in the following table:
398398

399-
| Component | Deprecation release | Target release for removal | Recommendation |
400-
|----------------------------------------------------------------------------------|---------------------|----------------------------|------------------------------------------|
401-
| Runtime V1 API and implementation (`io.containerd.runtime.v1.linux`) | containerd v1.4 | containerd v2.0 ✅ | Use `io.containerd.runc.v2` |
402-
| Runc V1 implementation of Runtime V2 (`io.containerd.runc.v1`) | containerd v1.4 | containerd v2.0 ✅ | Use `io.containerd.runc.v2` |
403-
| Built-in `aufs` snapshotter | containerd v1.5 | containerd v2.0 ✅ | Use `overlayfs` snapshotter |
404-
| Container label `containerd.io/restart.logpath` | containerd v1.5 | containerd v2.0 ✅ | Use `containerd.io/restart.loguri` label |
405-
| `cri-containerd-*.tar.gz` release bundles | containerd v1.6 | containerd v2.0 ✅ | Use `containerd-*.tar.gz` bundles |
406-
| Pulling Schema 1 images (`application/vnd.docker.distribution.manifest.v1+json`) | containerd v1.7 | containerd v2.0 | Use Schema 2 or OCI images |
407-
| CRI `v1alpha2` | containerd v1.7 | containerd v2.0 ✅ | Use CRI `v1` |
408-
| Legacy CRI implementation of podsandbox support | containerd v2.0 | containerd v2.0 ✅ | |
409-
| Go-Plugin library (`*.so`) as containerd runtime plugin | containerd v2.0 | containerd v2.1 | Use external plugins (proxy or binary) |
399+
| Component | Deprecation release | Target release for removal | Recommendation |
400+
|---------------------------------------------------------------------------------------|---------------------|----------------------------|------------------------------------------|
401+
| Runtime V1 API and implementation (`io.containerd.runtime.v1.linux`) | containerd v1.4 | containerd v2.0 ✅ | Use `io.containerd.runc.v2` |
402+
| Runc V1 implementation of Runtime V2 (`io.containerd.runc.v1`) | containerd v1.4 | containerd v2.0 ✅ | Use `io.containerd.runc.v2` |
403+
| Built-in `aufs` snapshotter | containerd v1.5 | containerd v2.0 ✅ | Use `overlayfs` snapshotter |
404+
| Container label `containerd.io/restart.logpath` | containerd v1.5 | containerd v2.0 ✅ | Use `containerd.io/restart.loguri` label |
405+
| `cri-containerd-*.tar.gz` release bundles | containerd v1.6 | containerd v2.0 ✅ | Use `containerd-*.tar.gz` bundles |
406+
| Pulling Schema 1 images (`application/vnd.docker.distribution.manifest.v1+prettyjws`) | containerd v1.7 | containerd v2.0 | Use Schema 2 or OCI images |
407+
| CRI `v1alpha2` | containerd v1.7 | containerd v2.0 ✅ | Use CRI `v1` |
408+
| Legacy CRI implementation of podsandbox support | containerd v2.0 | containerd v2.0 ✅ | |
409+
| Go-Plugin library (`*.so`) as containerd runtime plugin | containerd v2.0 | containerd v2.1 | Use external plugins (proxy or binary) |
410410

411411

412412
### Deprecated config properties

client/client.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,6 @@ type RemoteContext struct {
354354
// after it has completed transferring.
355355
HandlerWrapper func(images.Handler) images.Handler
356356

357-
// ConvertSchema1 is whether to convert Docker registry schema 1
358-
// manifests. If this option is false then any image which resolves
359-
// to schema 1 will return an error since schema 1 is not supported.
360-
//
361-
// Deprecated: use Schema 2 or OCI images.
362-
ConvertSchema1 bool
363-
364357
// Platforms defines which platforms to handle when doing the image operation.
365358
// Platforms is ignored when a PlatformMatcher is set, otherwise the
366359
// platforms will be used to create a PlatformMatcher with no ordering

client/client_opts.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,16 +197,6 @@ func WithChildLabelMap(fn func(ocispec.Descriptor) []string) RemoteOpt {
197197
}
198198
}
199199

200-
// WithSchema1Conversion is used to convert Docker registry schema 1
201-
// manifests to oci manifests on pull. Without this option schema 1
202-
// manifests will return a not supported error.
203-
//
204-
// Deprecated: use Schema 2 or OCI images.
205-
func WithSchema1Conversion(client *Client, c *RemoteContext) error {
206-
c.ConvertSchema1 = true
207-
return nil
208-
}
209-
210200
// WithResolver specifies the resolver to use.
211201
func WithResolver(resolver remotes.Resolver) RemoteOpt {
212202
return func(client *Client, c *RemoteContext) error {

client/pull.go

Lines changed: 46 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"github.com/containerd/containerd/v2/core/images"
2828
"github.com/containerd/containerd/v2/core/remotes"
2929
"github.com/containerd/containerd/v2/core/remotes/docker"
30-
"github.com/containerd/containerd/v2/core/remotes/docker/schema1" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
3130
"github.com/containerd/containerd/v2/pkg/tracing"
3231
"github.com/containerd/containerd/v2/pkg/unpack"
3332
"github.com/containerd/errdefs"
@@ -164,7 +163,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima
164163

165164
if unpacker != nil && ur.Unpacks == 0 {
166165
// Unpack was tried previously but nothing was unpacked
167-
// This is at least required for schema 1 image.
166+
// This was at least required for schema 1 image.
168167
if err := i.Unpack(ctx, pullCtx.Snapshotter, pullCtx.UnpackOpts...); err != nil {
169168
return nil, fmt.Errorf("failed to unpack image on snapshotter %s: %w", pullCtx.Snapshotter, err)
170169
}
@@ -190,70 +189,60 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim
190189
var (
191190
handler images.Handler
192191

193-
isConvertible bool
194-
originalSchema1Digest string
195-
converterFunc func(context.Context, ocispec.Descriptor) (ocispec.Descriptor, error)
196-
limiter *semaphore.Weighted
192+
isConvertible bool
193+
converterFunc func(context.Context, ocispec.Descriptor) (ocispec.Descriptor, error)
194+
limiter *semaphore.Weighted
197195
)
198196

199-
if desc.MediaType == images.MediaTypeDockerSchema1Manifest && rCtx.ConvertSchema1 {
200-
schema1Converter := schema1.NewConverter(store, fetcher)
201-
202-
handler = images.Handlers(append(rCtx.BaseHandlers, schema1Converter)...)
203-
204-
isConvertible = true
205-
206-
converterFunc = func(ctx context.Context, _ ocispec.Descriptor) (ocispec.Descriptor, error) {
207-
return schema1Converter.Convert(ctx)
208-
}
209-
210-
originalSchema1Digest = desc.Digest.String()
197+
if desc.MediaType == images.MediaTypeDockerSchema1Manifest {
198+
return images.Image{}, fmt.Errorf("%w: media type %q is no longer supported since containerd v2.0, please rebuild the image as %q or %q",
199+
errdefs.ErrNotImplemented,
200+
images.MediaTypeDockerSchema1Manifest, images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest)
201+
}
202+
// Get all the children for a descriptor
203+
childrenHandler := images.ChildrenHandler(store)
204+
// Set any children labels for that content
205+
childrenHandler = images.SetChildrenMappedLabels(store, childrenHandler, rCtx.ChildLabelMap)
206+
if rCtx.AllMetadata {
207+
// Filter manifests by platforms but allow to handle manifest
208+
// and configuration for not-target platforms
209+
childrenHandler = remotes.FilterManifestByPlatformHandler(childrenHandler, rCtx.PlatformMatcher)
211210
} else {
212-
// Get all the children for a descriptor
213-
childrenHandler := images.ChildrenHandler(store)
214-
// Set any children labels for that content
215-
childrenHandler = images.SetChildrenMappedLabels(store, childrenHandler, rCtx.ChildLabelMap)
216-
if rCtx.AllMetadata {
217-
// Filter manifests by platforms but allow to handle manifest
218-
// and configuration for not-target platforms
219-
childrenHandler = remotes.FilterManifestByPlatformHandler(childrenHandler, rCtx.PlatformMatcher)
220-
} else {
221-
// Filter children by platforms if specified.
222-
childrenHandler = images.FilterPlatforms(childrenHandler, rCtx.PlatformMatcher)
223-
}
224-
// Sort and limit manifests if a finite number is needed
225-
if limit > 0 {
226-
childrenHandler = images.LimitManifests(childrenHandler, rCtx.PlatformMatcher, limit)
227-
}
211+
// Filter children by platforms if specified.
212+
childrenHandler = images.FilterPlatforms(childrenHandler, rCtx.PlatformMatcher)
213+
}
214+
// Sort and limit manifests if a finite number is needed
215+
if limit > 0 {
216+
childrenHandler = images.LimitManifests(childrenHandler, rCtx.PlatformMatcher, limit)
217+
}
228218

229-
// set isConvertible to true if there is application/octet-stream media type
230-
convertibleHandler := images.HandlerFunc(
231-
func(_ context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
232-
if desc.MediaType == docker.LegacyConfigMediaType {
233-
isConvertible = true
234-
}
219+
// set isConvertible to true if there is application/octet-stream media type
220+
convertibleHandler := images.HandlerFunc(
221+
func(_ context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
222+
if desc.MediaType == docker.LegacyConfigMediaType {
223+
isConvertible = true
224+
}
235225

236-
return []ocispec.Descriptor{}, nil
237-
},
238-
)
226+
return []ocispec.Descriptor{}, nil
227+
},
228+
)
239229

240-
appendDistSrcLabelHandler, err := docker.AppendDistributionSourceLabel(store, ref)
241-
if err != nil {
242-
return images.Image{}, err
243-
}
230+
appendDistSrcLabelHandler, err := docker.AppendDistributionSourceLabel(store, ref)
231+
if err != nil {
232+
return images.Image{}, err
233+
}
244234

245-
handlers := append(rCtx.BaseHandlers,
246-
remotes.FetchHandler(store, fetcher),
247-
convertibleHandler,
248-
childrenHandler,
249-
appendDistSrcLabelHandler,
250-
)
235+
handlers := append(rCtx.BaseHandlers,
236+
remotes.FetchHandler(store, fetcher),
237+
convertibleHandler,
238+
childrenHandler,
239+
appendDistSrcLabelHandler,
240+
)
251241

252-
handler = images.Handlers(handlers...)
242+
handler = images.Handlers(handlers...)
253243

254-
converterFunc = func(ctx context.Context, desc ocispec.Descriptor) (ocispec.Descriptor, error) {
255-
return docker.ConvertManifest(ctx, store, desc)
256-
}
244+
converterFunc = func(ctx context.Context, desc ocispec.Descriptor) (ocispec.Descriptor, error) {
245+
return docker.ConvertManifest(ctx, store, desc)
257246
}
258247

259248
if rCtx.HandlerWrapper != nil {
@@ -274,13 +263,6 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim
274263
}
275264
}
276265

277-
if originalSchema1Digest != "" {
278-
if rCtx.Labels == nil {
279-
rCtx.Labels = make(map[string]string)
280-
}
281-
rCtx.Labels[images.ConvertedDockerSchema1LabelKey] = originalSchema1Digest
282-
}
283-
284266
return images.Image{
285267
Name: name,
286268
Target: desc,

cmd/ctr/commands/content/fetch.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,7 @@ func Fetch(ctx context.Context, client *containerd.Client, ref string, config *F
183183
}()
184184

185185
h := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
186-
if desc.MediaType != images.MediaTypeDockerSchema1Manifest {
187-
ongoing.Add(desc)
188-
}
186+
ongoing.Add(desc)
189187
return nil, nil
190188
})
191189

@@ -195,7 +193,6 @@ func Fetch(ctx context.Context, client *containerd.Client, ref string, config *F
195193
containerd.WithPullLabels(labels),
196194
containerd.WithResolver(config.Resolver),
197195
containerd.WithImageHandler(h),
198-
containerd.WithSchema1Conversion, //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
199196
}
200197
opts = append(opts, config.RemoteOpts...)
201198

core/images/labels.go

Lines changed: 0 additions & 21 deletions
This file was deleted.

core/remotes/docker/fetcher.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
9797
}
9898

9999
// Try manifests endpoints for manifests types
100-
if images.IsManifestType(desc.MediaType) || images.IsIndexType(desc.MediaType) ||
101-
desc.MediaType == images.MediaTypeDockerSchema1Manifest {
100+
if images.IsManifestType(desc.MediaType) || images.IsIndexType(desc.MediaType) {
102101

103102
var firstErr error
104103
for _, host := range r.hosts {

core/remotes/docker/resolver.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import (
3030

3131
"github.com/containerd/containerd/v2/core/images"
3232
"github.com/containerd/containerd/v2/core/remotes"
33-
"github.com/containerd/containerd/v2/core/remotes/docker/schema1" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
3433
remoteerrors "github.com/containerd/containerd/v2/core/remotes/errors"
3534
"github.com/containerd/containerd/v2/pkg/reference"
3635
"github.com/containerd/containerd/v2/pkg/tracing"
@@ -376,13 +375,8 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp
376375
}
377376

378377
if contentType == images.MediaTypeDockerSchema1Manifest {
379-
b, err := schema1.ReadStripSignature(&bodyReader)
380-
if err != nil {
381-
return err
382-
}
383-
384-
dgst = digest.FromBytes(b)
385-
return nil
378+
return fmt.Errorf("%w: media type %q is no longer supported since containerd v2.0, please rebuild the image as %q or %q",
379+
errdefs.ErrNotImplemented, images.MediaTypeDockerSchema1Manifest, images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest)
386380
}
387381

388382
dgst, err = digest.FromReader(&bodyReader)

0 commit comments

Comments
 (0)