regclient / regclient

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Issue] image mod on existing local image will generate additional manifest entry

qiuchengxuan opened this issue · comments

Current Behavior

qiuchengxuan@homelab:~ regctl image mod docker.io/busybox:latest --create ocidir://busybox:latest
ocidir://busybox:latest
qiuchengxuan@homelab:~ cat busybox/index.json
{"schemaVersion":2,"mediaType":"application/vnd.oci.image.index.v1+json","manifests":[{"mediaType":"application/vnd.oci.image.index.v1+json","digest":"sha256:5eef5ed34e1e1ff0a4ae850395cbf665c4de6b4b83a32a0bc7bcb998e24e7bbb","size":6761,"annotations":{"org.opencontainers.image.ref.name":"latest"}}]}%
qiuchengxuan@homelab:~ cat busybox/index.json | jq .
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.index.v1+json",
      "digest": "sha256:5eef5ed34e1e1ff0a4ae850395cbf665c4de6b4b83a32a0bc7bcb998e24e7bbb",
      "size": 6761,
      "annotations": {
        "org.opencontainers.image.ref.name": "latest"
      }
    }
  ]
}
qiuchengxuan@homelab:~ regctl image mod ocidir://busybox:latest --layer-compress none
ocidir://busybox@sha256:afede23b871997322960d0ebfba63cb1f92462fe8c62c5db50e83635c85432c8
qiuchengxuan@homelab:~ cat busybox/index.json | jq .
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.index.v1+json",
      "digest": "sha256:5eef5ed34e1e1ff0a4ae850395cbf665c4de6b4b83a32a0bc7bcb998e24e7bbb",
      "size": 6761,
      "annotations": {
        "org.opencontainers.image.ref.name": "latest"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.index.v1+json",
      "digest": "sha256:afede23b871997322960d0ebfba63cb1f92462fe8c62c5db50e83635c85432c8",
      "size": 6670
    }
  ]
}

Expected Behavior

Only one entry in manifests

Steps To Reproduce

  1. regctl image mod docker.io/busybox:latest --create ocidir://busybox:latest
  2. regctl image mod ocidir://busybox:latest --layer-compress none

Version

VCSTag:     v0.6.1
VCSRef:     766ee6291f882778207ff42207f9ca8b1da54e57
VCSCommit:  766ee6291f882778207ff42207f9ca8b1da54e57
VCSState:   clean
VCSDate:    2024-05-14T13:18:19Z
Platform:   linux/amd64
GoVer:      go1.22.3
GoCompiler: gc

Environment

  • Running as binary or container: binary
  • Host platform: linux/amd64
  • Registry description: docker.io

Anything else

There is a --replace flag buried in there that allows you to overwriting the existing tag instead of creating a new tag or falling back to pushing an untagged manifest:

$ regctl image mod --help
EXPERIMENTAL: Applies requested modifications to an image
For time options, the value is a comma separated list of key/value pairs:
  set=${time}: time to set in rfc3339 format, e.g. 2006-01-02T15:04:05Z
  from-label=${label}: label used to extract time in rfc3339 format
  after=${time_in_rfc3339}: adjust any time after this
  base-ref=${image}: image to lookup base layers, which are skipped
  base-layers=${count}: number of layers to skip changing (from the base image)
  Note: set or from-label is required in the time options

Usage:
  regctl image mod <image_ref> [flags]

Examples:

# add an annotation to all images, replacing the v1 tag with the new image
regctl image mod registry.example.org/repo:v1 \
  --replace --annotation '[*]org.opencontainers.image.created=2021-02-03T05:06:07Z

# convert an image to the OCI media types, copying to local registry
regctl image mod alpine:3.5 --to-oci --create registry.example.org/alpine:3.5

# append a layer to only the linux/amd64 image using the file.tar contents
regctl image mod registry.example.org/repo:v1 --create v1-extended \
  --layer-add "tar=file.tar,platform=linux/amd64"

# append a layer to all platforms using the contents of a directory
regctl image mod registry.example.org/repo:v1 --create v1-extended \
  --layer-add "dir=path/to/directory"

# set the timestamp on the config and layers, ignoring the alpine base image layers
regctl image mod registry.example.org/repo:v1 --create v1-mod \
  --time "set=2021-02-03T04:05:06Z,base-ref=alpine:3"

# set the entrypoint to be bash and unset the default command
regctl image mod registry.example.org/repo:v1 --create v1-bash \
  --config-entrypoint '["bash"]' --config-cmd ""

# Rebase an older regctl image, copying to the local registry.
# This uses annotations that were included in the original image build.
regctl image mod registry.example.org/regctl:v0.5.1-alpine \
  --rebase --create v0.5.1-alpine-rebase

Flags:
      --annotation stringArray        set an annotation (name=value, omit value to delete, prefix with platform list [p1,p2] or [*] for all images) (default )
      --annotation-base stringArray   set base image annotations (image/name:tag,sha256:digest) (default )
      --annotation-promote            promote common annotations from child images to index (default )
      --buildarg-rm string            delete a build arg (default "")
      --buildarg-rm-regex string      delete a build arg with a regex value (default "")
      --config-cmd string             set command in the config (json array or string, empty string to delete) (default "")
      --config-entrypoint string      set entrypoint in the config (json array or string, empty string to delete) (default "")
      --config-platform string        set platform on the config (not recommended for an index of multiple images) (default "")
      --config-time string            set timestamp for the config (default "")
      --create string                 Create image or tag
      --data-max stringArray          sets or removes descriptor data field (size in bytes) (default )
      --expose-add stringArray        add an exposed port (default )
      --expose-rm stringArray         delete an exposed port (default )
      --external-urls-rm              remove external url references from layers (first copy image with "--include-external") (default )
      --file-tar-time stringArray     timestamp for contents of a tar file within a layer, set filename=${name} with time options (default )
  -h, --help                          help for mod
      --label stringArray             set an label (name=value, omit value to delete, prefix with platform list [p1,p2] for subset of images) (default )
      --label-to-annotation           set annotations from labels (default )
      --layer-add string              add a new layer (tar=file,dir=directory,platform=val) (default "")
      --layer-compress string         change layer compression (gzip, none, zstd) (default "")
      --layer-rm-created-by string    delete a layer based on history (created by string is a regex) (default "")
      --layer-rm-index uint           delete a layer from an image (index begins at 0) (default )
      --layer-strip-file string       delete a file or directory from all layers (default "")
      --layer-time string             set timestamp for the layer contents (default "")
      --rebase                        rebase an image using OCI annotations (default )
      --rebase-ref string             rebase an image with base references (base:old,base:new) (default "")
      --replace                       Replace tag (ignored when "create" is used)
      --reproducible                  fix tar headers for reproducibility (default )
      --time string                   set timestamp for both the config and layers (default "")
      --to-docker                     convert to Docker schema2 media types (default )
      --to-oci                        convert to OCI media types (default )
      --to-oci-referrers              convert to OCI referrers (default )
      --volume-add stringArray        add a volume definition (default )
      --volume-rm stringArray         delete a volume definition (default )

Global Flags:
      --host stringArray     Registry hosts to add (reg=registry,user=username,pass=password,tls=enabled)
      --logopt stringArray   Log options
      --user-agent string    Override user agent
  -v, --verbosity string     Log level (debug, info, warn, error, fatal, panic) (default "warning")

Also, note that this command doesn't make much sense:

regctl image mod docker.io/busybox:latest --create ocidir://busybox:latest

It is performing a high overhead image copy. If you wanted to copy the image, you can use regctl image copy instead. Otherwise you could merge the two steps into one:

regctl image mod docker.io/busybox:latest --layer-compress none --create ocidir://busybox:latest