regclient / regclient

Docker and OCI Registry Client in Go and tooling using those libraries.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Feature] Support uncompressed layers

qiuchengxuan opened this issue · comments

Current Behavior

Layers are compressed with gzip

Expected Behavior

Able to export image with uncompressed layers, therefore able to compress image with xz

Example Solution

regctl image export --compress-layers none

Version

0.5.7

Environment

  • Running as binary:
  • Host platform: Linux x86
  • Registry description: registry:2

The regctl image export does not modify the image, that would change the digest. The compression of the layers is done by the image builder, and that would be the best place to change it.

Modifying an image to change the layer compression could potentially be done by regctl image mod. However, xz is not a supported OCI format, so the best that could be done is converting them to either zstd or uncompressed layers. On my longer term todo list is support for estargz and soci, which may impact this same code.

Thank you very much for your patience and quick reply

To verify, does changing the image, and its digest, matter for your use case? What is the purpose of uncompressing content and recompressing it in this scenario?

To verify, does changing the image, and its digest, matter for your use case? What is the purpose of uncompressing content and recompressing it in this scenario?

I read the regctl image mod, it seems not what I want, since it will modify image on registry. What I want is simply the same with docker pull mariadb:latest; docker save mariadb:latest | xz -T0, which inner layers is uncompressed, to archive maximum compress ratio, or able to modify image locally.

which inner layers is uncompressed, to archive maximum compress ratio, or able to modify image locally.

I'm still not understanding the use case.

  • Where are the images coming from and being pushed to, and how would they be consumed later?
  • What is being compressing with xz, the individual layers, or the tar of the overall image export?
  • Is filesystem usage important before the xz compression is run at the source or after the image is uncompressed at the destination?
  • Does the digest of the image need to remain the same, either because it was signed or images are pinned by a downstream consumer?
  • Is this being done for a single image, or will updates to the image also be recompressed with a similar pattern?
  • What other kinds of local image modifications do you want to perform?
  • Where are the images coming from and being pushed to, and how would they be consumed later?

We're sharing these images offline, with command like xzcat image.tar.xz | ctr -n k8s.io images import -.
Images are from public or private registries, and not gonna to push to another registry.

  • What is being compressing with xz, the individual layers, or the tar of the overall image export?

The tar of the overall image export

  • Is filesystem usage important before the xz compression is run at the source or after the image is uncompressed at the destination?

Since probably you mean destination is another registry, actually we're not importing this image to another registry.
Images are from public or private registries.

  • Does the digest of the image need to remain the same, either because it was signed or images are pinned by a downstream consumer?

Image digest probably needs to be the same, and the layers digest can be different.

  • Is this being done for a single image, or will updates to the image also be recompressed with a similar pattern?

Single image, in our case.

  • What other kinds of local image modifications do you want to perform?

Not gonna modify local image, all we need is simply minimize exported image size

  • Is filesystem usage important before the xz compression is run at the source or after the image is uncompressed at the destination?

Since probably you mean destination is another registry, actually we're not importing this image to another registry. Images are from public or private registries.

In the case of containerd, I believe they retain the original layers to ensure the image can be pushed again. By uncompressing the layers before importing into containerd, that would double the size of the image on disk at rest, once for the uncompressed tar, and a second copy for the extracted layer.

  • Does the digest of the image need to remain the same, either because it was signed or images are pinned by a downstream consumer?

Image digest probably needs to be the same, and the layers digest can be different.

That is not technically possible. The image digest is of the image manifest. That manifest contains the digests of each layer. By uncompressing those layers, the digest of the layer changes, which causes the digest of the manifest to change.

In the case of docker pull && docker save, that does change the image digest because they are recreating the filesystem layers and the image manifest. It is also a lossy process, removing other platforms in a multi-platform image, and rebuilding the manifest without annotations or other content included by the original image author.

Using regctl image mod could improve on what docker pull && docker save is doing by preserving most of the manifest content. The output of regctl image mod can also be a local OCI Layout, avoiding the need to push to a registry. You would then be able to export from the Layout (newer versions of Docker will be able to import directly from an OCI Layout) into a tar and compress that with xz.

That still has the issue of containerd potentially storing the uncompressed layers twice, so I'd want to be sure you really want that before prioritizing this.

Modifying an image to change the layer compression could potentially be done by regctl image mod. However, xz is not a > supported OCI format, so the best that could be done is converting them to either zstd or uncompressed layers. On my longer term todo list is support for estargz and soci, which may impact this same code.

I finally got how to use this regctl image mod, it will be ok if I can use this to uncompress layers, which seems not present yet.

I finally got how to use this regctl image mod, it will be ok if I can use this to uncompress layers, which seems not present yet.

Thanks for the follow up. I'll work on adding that as a feature.

I finally got how to use this regctl image mod, it will be ok if I can use this to uncompress layers, which seems not present yet.

Thanks for the follow up. I'll work on adding that as a feature.

Many thanks~~

This should be supported now, though my recommendation is to hold off for zstd support to get added and use that rather than an uncompressed export that's later compressed with xz. The zstd compression is supported by some runtimes, allowing you to not need to decompress the layers at the destination to import the image.

FYI, #732 was just added to support zstd compression of the layers.

FYI, #732 was just added to support zstd compression of the layers.

emmm can't I modify an image locally, without uploading to any registry?

emmm can't I modify an image locally, without uploading to any registry?

You can! ocidir://path:tag is used to reference an image in an OCI Layout with regclient. E.g.

$ regctl image mod --layer-compress zstd \
  alpine@sha256:6457d53fb065d6f250e1504b9bc42d5b6c65941d57532c072d929dd0628977d0 \
  --create ocidir://alpine:zstd
ocidir://alpine:zstd

$ regctl manifest get ocidir://alpine:zstd
Name:        ocidir://alpine:zstd
MediaType:   application/vnd.docker.distribution.manifest.v2+json
Digest:      sha256:77f9bad60e1f844ae75fb5eb5749b924cfade5e0985ce6cde455970e86192d55
Total Size:  3.430MB

Config:
  Digest:    sha256:bc4e4f799925f2f66d0f70f97d9fed87410475f6f1df8a3e148cf0fc987c17b6
  MediaType: application/vnd.docker.container.image.v1+json
  Size:      585B

Layers:

  Digest:    sha256:27ffef933c817c18517d6a0f6490e4567acbef61375393893f1ea5dafc79e363
  MediaType: application/vnd.docker.image.rootfs.diff.tar.zstd
  Size:      3.430MB

emmm can't I modify an image locally, without uploading to any registry?

You can! ocidir://path:tag is used to reference an image in an OCI Layout with regclient. E.g.

$ regctl image mod --layer-compress zstd \
  alpine@sha256:6457d53fb065d6f250e1504b9bc42d5b6c65941d57532c072d929dd0628977d0 \
  --create ocidir://alpine:zstd
ocidir://alpine:zstd

$ regctl manifest get ocidir://alpine:zstd
Name:        ocidir://alpine:zstd
MediaType:   application/vnd.docker.distribution.manifest.v2+json
Digest:      sha256:77f9bad60e1f844ae75fb5eb5749b924cfade5e0985ce6cde455970e86192d55
Total Size:  3.430MB

Config:
  Digest:    sha256:bc4e4f799925f2f66d0f70f97d9fed87410475f6f1df8a3e148cf0fc987c17b6
  MediaType: application/vnd.docker.container.image.v1+json
  Size:      585B

Layers:

  Digest:    sha256:27ffef933c817c18517d6a0f6490e4567acbef61375393893f1ea5dafc79e363
  MediaType: application/vnd.docker.image.rootfs.diff.tar.zstd
  Size:      3.430MB

Thanks, I'll try this later