Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync on-demand: docker pull fails for OCI image index(application/vnd.oci.image.index.v1+json) #2836

Open
tamilhce opened this issue Dec 17, 2024 Discussed in #2811 · 33 comments
Labels
awaiting-answers rm-external Roadmap item submitted by non-maintainers

Comments

@tamilhce
Copy link
Contributor

Discussed in #2811

Originally posted by tamilhce November 28, 2024
I was running zot with following patch version https://github.com/tamilhce/zot/pull/13/ as a pull through for ECR

I have verified that some multi-arch images are working as expected, while others are not. Upon further investigation, I found that container multi-arch images with the type application/vnd.oci.image.index.v1+json (the OCI manifest list for multi-platform images) are not supported. Only multi-arch images with the Docker manifest format, application/vnd.docker.distribution.manifest.list.v2+json (the Docker manifest list for multi-platform images), are supported.

AWS ECR supports both the OCI and Docker manifest formats, whereas Zot only supports the multi-arch/image index of the Docker manifest format.

working - application/vnd.docker.distribution.manifest.list.v2+json

vanan@a-a7ehvnb8bz4k ~> docker manifest inspect xxxx.dkr.ecr.us-east-1.amazonaws.com/xxxx:v1.31.0-1.31.0
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 921,
         "digest": "sha256:8afaacbf5f90e424d6e70b5ffdc2447112c58031e830e994142fc500064a200f",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 921,
         "digest": "sha256:308b87952a99f44281fadcd7a490b7e8a7cbbb4d3c672ecb417a9b4064a6a316",
         "platform": {
            "architecture": "arm64",
            "os": "linux"
         }
      }
   ]
}


vanan@a-a7ehvnb8bz4k ~> docker pull zot-dev.xxx.net/xxxxx:v1.31.0-1.31.0
v1.31.0-1.31.0: Pulling from xxxxx
Digest: sha256:ca04f21bc8fcc278acb9bb4f08e359603d3b18da4384822c11e2771480d52a2b
Status: Image is up to date for zot-dev.xxx.net/xxxx:v1.31.0-1.31.0
zot-dev.xxx.net/xxxx:v1.31.0-1.31.0

Not working - application/vnd.oci.image.index.v1+json

vanan@xxxxx ~> docker manifest inspect xxxxxxx.dkr.ecr.us-east-1.amazonaws.com/xxxxxx:xxxxx
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.oci.image.index.v1+json",
   "manifests": [
      {
         "mediaType": "application/vnd.oci.image.manifest.v1+json",
         "size": 4841,
         "digest": "sha256:eea456504e848927b80b42427a2b466e25f7ddc226d18765912936001fda6288",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.oci.image.manifest.v1+json",
         "size": 4843,
         "digest": "sha256:5a6a7e7e93c854dc0f7df8c4ee669c3ba4a30bee27362bb194ba1defbbcb1409",
         "platform": {
            "architecture": "arm64",
            "os": "linux"
         }
      }
   ]
}


vanan@a-a7ehvnb8bz4k ~> docker pull zot-dev.xxx.net/xxxxx:xxxxx
Error response from daemon: repository zot-dev.xxx.net/xxxxx not found: name unknown: repository name not known to registry


relevant zot container error log 
{"level":"info","repo":"xxxx/xxxxx","xxxxx":"reference","err":"media type is not supported

is this the expected behavior? If it's a bug, I will work on the feature. Looking forward to your valuable reply.

@andaaron
Copy link
Contributor

@tamilhce

  1. Zot supports OCI image indexes in general, and it has been for about 2 years. By support I mean every call mentioned in the oci distribution spec. We have tests for all those scenarios.

  2. The issue you are reporting is specific to zot sync, so I think that should be captured in the issue title.
    Even for zot sync this is really strange, as we do support OCI indexes, and we do have tests for it, such as https://github.com/project-zot/zot/blob/main/pkg/extensions/sync/sync_test.go#L6935

As I asked in #2811, what call is docker actually making to the zot server? Can you share more of the logs?
Do different client tools (such as skopeo for example) work?

@andaaron andaaron changed the title zot not supporting OCI image index(application/vnd.oci.image.index.v1+json) zot sync on-demand: docker pull fails for OCI image index(application/vnd.oci.image.index.v1+json) Dec 17, 2024
@andaaron andaaron changed the title zot sync on-demand: docker pull fails for OCI image index(application/vnd.oci.image.index.v1+json) sync on-demand: docker pull fails for OCI image index(application/vnd.oci.image.index.v1+json) Dec 17, 2024
@tamilhce
Copy link
Contributor Author

tamilhce commented Dec 18, 2024

we have an ECR registry and have configured Zot as a pull-through cache (on-demand).
I observed that performing a docker pull directly from ECR as well as through zot works as expected for the media type "vnd.docker.distribution.manifest.list.v2+json".

However, when attempting a docker pull through Zot for the following OCI manifest, the pull fails:

 ~> docker manifest inspect ecrrepo/appname:1542762016
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.oci.image.index.v1+json",
   "manifests": [
      {
         "mediaType": "application/vnd.oci.image.manifest.v1+json",
         "size": 4841,
         "digest": "sha256:eea456504e848927b80b42427a2b466e25f7ddc226d18765912936001fda6288",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.oci.image.manifest.v1+json",
         "size": 4843,
         "digest": "sha256:5a6a7e7e93c854dc0f7df8c4ee669c3ba4a30bee27362bb194ba1defbbcb1409",
         "platform": {
            "architecture": "arm64",
            "os": "linux"
         }
      }
   ]
}

While docker pull directly from ECR works, the same operation through Zot fails. I do not believe this is a client-side issue. Below are relevant log messages for reference

  • docker command
]> docker pull zot/appname:1590357999
Error response from daemon: repository zot/ecrrepo/appname not found: name unknown: repository name not known to registry
vanan@a-a7ehvnb8bz4k ~ [1]> docker pull ecrrepo/appname:1590357999
1590357999: Pulling from ecrrepo/appname
9088cdb84e39: Already exists
---
c9ca5fb0e249: Pull complete
Digest: sha256:117717899b06c24a7a1008a92e503acbc400626df462d05e8175cb4eb7e38f67
Status: Downloaded newer image for ecrrepo/appname:1590357999

  • zot logs
{"level":"info","module":"http","component":"session","clientIP":"100.80.12.72:22225","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept-Encoding":["gzip"],"User-Agent":["docker/25.0.6 go/go1.22.5 git-commit/b08a51f kernel/5.15.167-112.165.amzn2.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/25.0.5 \\(linux\\))"],"X-Amzn-Trace-Id":["Root=1-6762a921-0c73db7e144f37276bfb5550"],"X-Forwarded-For":["10.12.245.41"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"goroutine":263343,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2024-12-18T10:51:13.635698457Z","message":"HTTP API"}
{"level":"info","repository":"appname","reference":"1590357999","goroutine":252054,"caller":"zotregistry.dev/zot/pkg/api/routes.go:2023","time":"2024-12-18T10:51:13.835288399Z","message":"trying to get updated image by syncing on demand"}
{"level":"info","goroutine":252056,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:562","time":"2024-12-18T10:51:13.835328042Z","message":"getting available client"}
{"level":"info","url":"674283286888.dkr.ecr.us-east-1.amazonaws.com","goroutine":252056,"caller":"zotregistry.dev/zot/pkg/extensions/sync/ecr_credential_helper.go:126","time":"2024-12-18T10:51:14.761798199Z","message":"The credentials are close to expiring"}
{"level":"info","url":"674283286888.dkr.ecr.us-east-1.amazonaws.com","goroutine":252056,"caller":"zotregistry.dev/zot/pkg/extensions/sync/ecr_credential_helper.go:135","time":"2024-12-18T10:51:14.76182424Z","message":"Refreshing the ECR credentials"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.19.37:40720","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":263403,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2024-12-18T10:51:15.945545158Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.19.37:40722","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":263402,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2024-12-18T10:51:15.945905526Z","message":"HTTP API"}
{"level":"info","url":"674283286888.dkr.ecr.us-east-1.amazonaws.com","goroutine":252056,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:170","time":"2024-12-18T10:51:18.190441504Z","message":"Refreshing the upstream remote registry credentials"}
{"level":"info","remote":"ecrrepo","repository":"appname","reference":"1590357999","goroutine":252056,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:364","time":"2024-12-18T10:51:18.190504252Z","message":"syncing image"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.14.110:44824","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":252128,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2024-12-18T10:51:18.943599706Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.14.110:44826","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":252193,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2024-12-18T10:51:18.943631903Z","message":"HTTP API"}
{"level":"error","error":"media type is not supported","repository":"appname","reference":"1590357999","goroutine":252056,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:481","time":"2024-12-18T10:51:21.733418182Z","message":"couldn't get upstream image manifest details"}
{"level":"error","error":"media type is not supported","repository":"appname","reference":"1590357999","goroutine":252054,"caller":"zotregistry.dev/zot/pkg/api/routes.go:2027","time":"2024-12-18T10:51:21.733518301Z","message":"failed to sync image"}
{"level":"info","repo":"appname","1590357999":"reference","err":"media type is not supported","component":"sync","goroutine":252186,"caller":"zotregistry.dev/zot/pkg/extensions/sync/on_demand.go:157","time":"2024-12-18T10:51:21.733556202Z","message":"starting routine to copy image, because of error"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.19.37:25330","method":"HEAD","path":"/v2/appname/manifests/1590357999","statusCode":404,"latency":"8s","bodySize":220,"headers":{"Accept":["application/json","application/vnd.docker.distribution.manifest.v2+json","application/vnd.docker.distribution.manifest.list.v2+json","application/vnd.oci.image.index.v1+json","application/vnd.oci.image.manifest.v1+json","application/vnd.docker.distribution.manifest.v1+prettyjws"],"User-Agent":["docker/25.0.6 go/go1.22.5 git-commit/b08a51f kernel/5.15.167-112.165.amzn2.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/25.0.5 \\(linux\\))"],"X-Amzn-Trace-Id":["Root=1-6762a921-592230577623e5fb15bfff99"],"X-Forwarded-For":["10.12.245.41"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"goroutine":252054,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2024-12-18T10:51:22.148116084Z","message":"HTTP API"}
{"level":"info","repository":"appname","reference":"1590357999","goroutine":263477,"caller":"zotregistry.dev/zot/pkg/api/routes.go:2023","time":"2024-12-18T10:51:22.347902584Z","message":"trying to get updated image by syncing on demand"}
{"level":"info","goroutine":263445,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:562","time":"2024-12-18T10:51:22.347954106Z","message":"getting available client"}
{"level":"info","url":"674283286888.dkr.ecr.us-east-1.amazonaws.com","goroutine":263445,"caller":"zotregistry.dev/zot/pkg/extensions/sync/ecr_credential_helper.go:126","time":"2024-12-18T10:51:23.090439687Z","message":"The credentials are close to expiring"}
{"level":"info","url":"674283286888.dkr.ecr.us-east-1.amazonaws.com","goroutine":263445,"caller":"zotregistry.dev/zot/pkg/extensions/sync/ecr_credential_helper.go:135","time":"2024-12-18T10:51:23.090472688Z","message":"Refreshing the ECR credentials"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.19.37:47038","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":263526,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2024-12-18T10:51:25.945641465Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.19.37:47040","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":263527,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2024-12-18T10:51:25.945652985Z","message":"HTTP API"}
{"level":"info","url":"674283286888.dkr.ecr.us-east-1.amazonaws.com","goroutine":263445,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:170","time":"2024-12-18T10:51:26.509986629Z","message":"Refreshing the upstream remote registry credentials"}
{"level":"info","remote":"ecrrepo","repository":"appname","reference":"1590357999","goroutine":263445,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:364","time":"2024-12-18T10:51:26.510065991Z","message":"syncing image"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.14.110:58150","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":252196,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2024-12-18T10:51:28.943823803Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.14.110:58148","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":252195,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2024-12-18T10:51:28.943823799Z","message":"HTTP API"}
{"level":"error","error":"media type is not supported","repository":"appname","reference":"1590357999","goroutine":263445,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:481","time":"2024-12-18T10:51:29.704646557Z","message":"couldn't get upstream image manifest details"}
{"level":"info","repo":"appname","1590357999":"reference","err":"media type is not supported","component":"sync","goroutine":263516,"caller":"zotregistry.dev/zot/pkg/extensions/sync/on_demand.go:157","time":"2024-12-18T10:51:29.704801321Z","message":"starting routine to copy image, because of error"}
{"level":"error","error":"media type is not supported","repository":"appname","reference":"1590357999","goroutine":263477,"caller":"zotregistry.dev/zot/pkg/api/routes.go:2027","time":"2024-12-18T10:51:29.704829701Z","message":"failed to sync image"}

This log line

{"level":"info","module":"http","component":"session","clientIP":"100.80.19.37:25330","method":"HEAD","path":"/v2/appname/manifests/1590357999","statusCode":404,"latency":"8s","bodySize":220,"headers":{"Accept":["application/json","application/vnd.docker.distribution.manifest.v2+json","application/vnd.docker.distribution.manifest.list.v2+json","application/vnd.oci.image.index.v1+json","application/vnd.oci.image.manifest.v1+json","application/vnd.docker.distribution.manifest.v1+prettyjws"]

indicates that /v2/appname/manifests/1590357999 was not in the accepted media types. However, the image manifest (as confirmed by the manifest inspect I shared earlier) shows that it is in one of the accepted media types. looks like an bug. still I didn't had a chance to review the code.

@andaaron
Copy link
Contributor

{"level":"error","error":"media type is not supported","repository":"appname","reference":"1590357999","goroutine":252056,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:481","time":"2024-12-18T10:51:21.733418182Z","message":"couldn't get upstream image manifest details"} this would be the relevant message. https://github.com/project-zot/zot/blob/main/pkg/extensions/sync/service.go#L426

Question is why it fails to get the image details. It is possible it fails to get the manifest from ecr (instead of having an issue with the manifest content)? Maybe it errors here https://github.com/project-zot/zot/blob/main/pkg/extensions/sync/remote.go#L132 ?

@tamilhce
Copy link
Contributor Author

I have verified the following:

  • This is not a permission issue, as Zot is able to pull other images.
  • The manifest is not malformed because docker pull works on ECR.
  • I’m not sure why retrieving the manifest fails for "mediaType": "application/vnd.oci.image.index.v1+json".

@andaaron
Copy link
Contributor

The strange part is it fails before our checks for manifest media type value.
I need to reproduce myself.

@tamilhce
Copy link
Contributor Author

@andaaron Thanks for linking the relevant code path. I will run a few more tests tomorrow and provide an update here.

I appreciate your quick response—it’s really helpful!

@andaaron
Copy link
Contributor

andaaron commented Dec 18, 2024

Some other limitation about the way sync works with multiarch at the moment:

  1. if periodic sync pulls the image it is usually the image index getting pulled
  2. if on-demand sync pulls the image, the client may explicitly make the request for a specific architecture where the client runs, and only that manifest for that arch would be copied over.
    In both cases 1 and 2, you would end up with the same repo name and same tag after the sync. Even tough the tag points to something else.

There's a PR for replacing the libraries used for sync, but due to limited time on the part of the contributor, it has been dragging for a long time.

@tamilhce
Copy link
Contributor Author

Could you please share the PR link? I’ll give it a try with that branch

@andaaron
Copy link
Contributor

This is the PR, but I don't think it's ready to be used at the moment: #2524

@andaaron
Copy link
Contributor

andaaron commented Dec 26, 2024

Hi @tamilhce,

I have tried to reproduce this issue, with a more basic configuration (as I don't have access to ECR, and also the zot configuration was not provided in the bug description).
Everything went fine. So we need to refine the steps to reproduce.

I tried using 2 zot instances.

1st zot has the config:

{
    "distSpecVersion": "1.1.0",
    "storage": {
        "rootDirectory": "/data/hdd/zot2"
    },
    "http": {
        "address": "0.0.0.0",
        "port": "5000",
        "realm": "zot"
    },
    "log": {
        "level": "debug",
        "output": "/data/hdd/zot2.log"
    },
    "extensions": {
        "search": {
            "enable": true,
            "cve": {
                "updateInterval": "2h"
            }
        }
    }
}

2nd zot has the config:

{
    "distSpecVersion": "1.1.0",
    "storage": {
        "rootDirectory": "/data/hdd/zot3"
    },
    "http": {
        "address": "0.0.0.0",
        "port": "5001",
        "realm": "zot"
    },
    "log": {
        "level": "debug",
        "output": "/data/hdd/zot3.log"
    },
    "extensions": {
        "sync": {
            "enable": true,
            "registries": [
                {
                    "urls": [
                        "http://localhost:5000"
                    ],
                    "onDemand": true,
                    "maxRetries": 6,
                    "tlsVerify": false,
                    "retryDelay": "5m"
                }
            ]
        }
    }
}

I uploaded images to the 1st zot using:
skopeo --insecure-policy copy --dest-tls-verify=false --format=oci --multi-arch=all docker://debian:bookworm docker://127.0.0.1:5000/debian:bookworm

I checked the repo/image/tag is present on zot running on port 5000:

{
    "manifests": [
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "amd64",
                "org.opencontainers.image.base.name": "scratch",
                "org.opencontainers.image.created": "2024-12-23T00:00:00Z",
                "org.opencontainers.image.revision": "e3f216064528d0ad005524fbafbddfd3115be946",
                "org.opencontainers.image.source": "https://github.com/debuerreotype/docker-debian-artifacts.git",
                "org.opencontainers.image.url": "https://hub.docker.com/_/debian",
                "org.opencontainers.image.version": "bookworm"
            },
            "digest": "sha256:cd73f5c112f19fac6d67b49d8982104fcf9c14b4ad69c2658fab8702f61b4430",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "amd64",
                "os": "linux"
            },
            "size": 1021
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "amd64",
                "vnd.docker.reference.digest": "sha256:cd73f5c112f19fac6d67b49d8982104fcf9c14b4ad69c2658fab8702f61b4430",
                "vnd.docker.reference.type": "attestation-manifest"
            },
            "digest": "sha256:834412f119e26e44d9de46da5bf43fb95e5f3570bd568d3d429ce384f8f9d653",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "unknown",
                "os": "unknown"
            },
            "size": 562
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "arm32v5",
                "org.opencontainers.image.base.name": "scratch",
                "org.opencontainers.image.created": "2024-12-23T00:00:00Z",
                "org.opencontainers.image.revision": "96ae5cf33b922b1ebe0b394a0488bd8f41591f2c",
                "org.opencontainers.image.source": "https://github.com/debuerreotype/docker-debian-artifacts.git",
                "org.opencontainers.image.url": "https://hub.docker.com/_/debian",
                "org.opencontainers.image.version": "bookworm"
            },
            "digest": "sha256:ee7a87661b1d6ca62839cd582b04738ea6020137b2ce56170f4f74de940caff6",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "arm",
                "os": "linux",
                "variant": "v5"
            },
            "size": 1041
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "arm32v5",
                "vnd.docker.reference.digest": "sha256:ee7a87661b1d6ca62839cd582b04738ea6020137b2ce56170f4f74de940caff6",
                "vnd.docker.reference.type": "attestation-manifest"
            },
            "digest": "sha256:af80ff0dde8185b4091a20c02feabdf4d2eeef261a466be65779ecf79bd9f0a2",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "unknown",
                "os": "unknown"
            },
            "size": 562
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "arm32v7",
                "org.opencontainers.image.base.name": "scratch",
                "org.opencontainers.image.created": "2024-12-23T00:00:00Z",
                "org.opencontainers.image.revision": "997dca5116e3abb92ac42a8ce895c96f53a321a4",
                "org.opencontainers.image.source": "https://github.com/debuerreotype/docker-debian-artifacts.git",
                "org.opencontainers.image.url": "https://hub.docker.com/_/debian",
                "org.opencontainers.image.version": "bookworm"
            },
            "digest": "sha256:efc40768fcd228826b95493f05f718304349762b8ea5344ddb45032334f421b7",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "arm",
                "os": "linux",
                "variant": "v7"
            },
            "size": 1041
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "arm32v7",
                "vnd.docker.reference.digest": "sha256:efc40768fcd228826b95493f05f718304349762b8ea5344ddb45032334f421b7",
                "vnd.docker.reference.type": "attestation-manifest"
            },
            "digest": "sha256:785674b6ee4ea1eab93cb47872e8ceaebf1cc6f379cdb322020def71583dfc54",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "unknown",
                "os": "unknown"
            },
            "size": 562
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "arm64v8",
                "org.opencontainers.image.base.name": "scratch",
                "org.opencontainers.image.created": "2024-12-23T00:00:00Z",
                "org.opencontainers.image.revision": "a9c3518f26dd0c08a2625127d5baebeae3eba8e8",
                "org.opencontainers.image.source": "https://github.com/debuerreotype/docker-debian-artifacts.git",
                "org.opencontainers.image.url": "https://hub.docker.com/_/debian",
                "org.opencontainers.image.version": "bookworm"
            },
            "digest": "sha256:5d99d20795032654a4d76a464cbd9733a5f0fc3911b6f2a36c1d51211b104afe",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "arm64",
                "os": "linux",
                "variant": "v8"
            },
            "size": 1041
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "arm64v8",
                "vnd.docker.reference.digest": "sha256:5d99d20795032654a4d76a464cbd9733a5f0fc3911b6f2a36c1d51211b104afe",
                "vnd.docker.reference.type": "attestation-manifest"
            },
            "digest": "sha256:e6dafd27815785aa7d0dc7651b1d19b45155043d42bcc4ff68ddb9fd9ebc8375",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "unknown",
                "os": "unknown"
            },
            "size": 562
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "i386",
                "org.opencontainers.image.base.name": "scratch",
                "org.opencontainers.image.created": "2024-12-23T00:00:00Z",
                "org.opencontainers.image.revision": "d378bbefca06de15e86ce242c1882991cb205bc4",
                "org.opencontainers.image.source": "https://github.com/debuerreotype/docker-debian-artifacts.git",
                "org.opencontainers.image.url": "https://hub.docker.com/_/debian",
                "org.opencontainers.image.version": "bookworm"
            },
            "digest": "sha256:8ec223efa3a7312781a078ed3557fd5a780d06c6ef047a34f72391f4462c514e",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "386",
                "os": "linux"
            },
            "size": 1017
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "i386",
                "vnd.docker.reference.digest": "sha256:8ec223efa3a7312781a078ed3557fd5a780d06c6ef047a34f72391f4462c514e",
                "vnd.docker.reference.type": "attestation-manifest"
            },
            "digest": "sha256:37f5c2ec14ef40dd026b37e3d059560b2d10c9ab5f001e40bd6130e3d08b139d",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "unknown",
                "os": "unknown"
            },
            "size": 562
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "mips64le",
                "org.opencontainers.image.base.name": "scratch",
                "org.opencontainers.image.created": "2024-12-23T00:00:00Z",
                "org.opencontainers.image.revision": "f143b23838b95457b64fa753ce2dec022ac0e4d0",
                "org.opencontainers.image.source": "https://github.com/debuerreotype/docker-debian-artifacts.git",
                "org.opencontainers.image.url": "https://hub.docker.com/_/debian",
                "org.opencontainers.image.version": "bookworm"
            },
            "digest": "sha256:b5d9524f3fedef64ec6ea84c2e1b3f2ba93b65bce3111625d8990549dc90fd2b",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "mips64le",
                "os": "linux"
            },
            "size": 1029
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "ppc64le",
                "org.opencontainers.image.base.name": "scratch",
                "org.opencontainers.image.created": "2024-12-23T00:00:00Z",
                "org.opencontainers.image.revision": "8ae00f32f3662f944b54eef8f8032bc2eca984ac",
                "org.opencontainers.image.source": "https://github.com/debuerreotype/docker-debian-artifacts.git",
                "org.opencontainers.image.url": "https://hub.docker.com/_/debian",
                "org.opencontainers.image.version": "bookworm"
            },
            "digest": "sha256:0ba38f2a08bbe9100915562c4ce576613ae064c60ccc349483a80f29215f139c",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "ppc64le",
                "os": "linux"
            },
            "size": 1029
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "ppc64le",
                "vnd.docker.reference.digest": "sha256:0ba38f2a08bbe9100915562c4ce576613ae064c60ccc349483a80f29215f139c",
                "vnd.docker.reference.type": "attestation-manifest"
            },
            "digest": "sha256:ab38f9b910a87bcec1d2a528b1d1bef1bd7895066ed12496f81c2cd3324475ec",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "unknown",
                "os": "unknown"
            },
            "size": 562
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "s390x",
                "org.opencontainers.image.base.name": "scratch",
                "org.opencontainers.image.created": "2024-12-23T00:00:00Z",
                "org.opencontainers.image.revision": "f8db2aed5e329e25f933ebfef0505f9665e2f2d4",
                "org.opencontainers.image.source": "https://github.com/debuerreotype/docker-debian-artifacts.git",
                "org.opencontainers.image.url": "https://hub.docker.com/_/debian",
                "org.opencontainers.image.version": "bookworm"
            },
            "digest": "sha256:355db701f3b391739cb2e6b57b3943032c5e4b89062d42e96cee089d5c3f16f7",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "s390x",
                "os": "linux"
            },
            "size": 1021
        },
        {
            "annotations": {
                "com.docker.official-images.bashbrew.arch": "s390x",
                "vnd.docker.reference.digest": "sha256:355db701f3b391739cb2e6b57b3943032c5e4b89062d42e96cee089d5c3f16f7",
                "vnd.docker.reference.type": "attestation-manifest"
            },
            "digest": "sha256:1d6a87f65d816d20c735234d8bc7393be525d154a74e3fa139fc6770b00ded63",
            "mediaType": "application/vnd.oci.image.manifest.v1+json",
            "platform": {
                "architecture": "unknown",
                "os": "unknown"
            },
            "size": 562
        }
    ],
    "mediaType": "application/vnd.oci.image.index.v1+json",
    "schemaVersion": 2
}

After that I pulled from the 2nd zot.
docker pull 127.0.0.1:5001/debian:bookworm
Which went through fine, and I also checked the tag on the 2nd zot, and it points to the same content as on the 1st zot.

@andaaron
Copy link
Contributor

andaaron commented Dec 26, 2024

I also tried using a build from your branch tamilhce/ecr-cred-helper for the 2nd zot (note there's a go.mod change you haven't committed, and it shows after go mod tidy). The sync was successful, the issue did not reproduce

@rchincha rchincha added the rm-external Roadmap item submitted by non-maintainers label Dec 31, 2024
@tamilhce
Copy link
Contributor Author

tamilhce commented Jan 7, 2025

Hi @andaaron,
Due to family medical reasons, I have not been working for the past couple of weeks. I might need to extend this for another one or two weeks. Once I return, we can connect, or I will share the reproducer with you to move things forward.

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 3, 2025

Hi @andaaron, sure I will reprod the issue locally and share the steps to proceed further.

@andaaron
Copy link
Contributor

andaaron commented Feb 3, 2025

Note we want to merge #2903 soon. Which is a substantial rewrite of the sync logic.

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 5, 2025

I tried reproducing the issue locally. This is what I observed:

When I copied the image from ECR to Zot1 and used Zot as the upstream registry, configuring Zot2 for sync on-demand exactly as you mentioned, it worked without any issues for the same image.

zot version

 zot -v
{"level":"info","distribution-spec":"1.1.0","commit":"v2.1.3-rc2-0-g05823cd","binary-type":"-imagetrust-lint-metrics-mgmt-profile-scrub-search-sync-ui-userprefs","go version":"go1.23.5","time":"2025-02-05T02:23:08-05:00","message":"version"}

zot1

{
    "distSpecVersion": "1.1.0",
    "storage": {
        "rootDirectory": "/tmp/hdd/zot1"
    },
    "http": {
        "address": "0.0.0.0",
        "port": "5000",
        "realm": "zot"
    },
    "log": {
        "level": "debug",
        "output": "/tmp/hdd/zot1.log"
    },
    "extensions": {
        "search": {
            "enable": true,
            "cve": {
                "updateInterval": "2h"
            }
        }
    }
}

zot2

{
    "distSpecVersion": "1.1.0",
    "storage": {
        "rootDirectory": "/tmp/hdd/zot2"
    },
    "http": {
        "address": "0.0.0.0",
        "port": "5001",
        "realm": "zot"
    },
    "log": {
        "level": "debug",
        "output": "/tmp/hdd/zot2.log"
    },
    "extensions": {
        "sync": {
            "enable": true,
            "registries": [
                {
                    "urls": [
                        "http://localhost:5000"
                    ],
                    "onDemand": true,
                    "maxRetries": 6,
                    "tlsVerify": false,
                    "retryDelay": "5m"
                }
            ]
        }
  • copy image to zot2

aws ecr get-authorization-token | jq -r '.authorizationData[0].authorizationToken' | base64 -d | cut -d: -f2 | skopeo login -u AWS --password-stdin accountid.dkr.ecr.us-east-1.amazonaws.com

skopeo --insecure-policy copy --dest-tls-verify=false --format=oci --all docker://test-image:1542762016 docker:// zot-reg.net:5000/test-image:1

on-demand sync

[vanan@vanan-registry-test-1 (shared-dev.i dev) ~]$ sudo docker pull 127.0.0.1:5001/test-image:1
1: Pulling from pricing-engine
9088cdb84e39: Pull complete 
c148a8383401: Pull complete 
1d71cb523366: Pull complete 
0f09c3747a0f: Pull complete 
ecc087031dc8: Pull complete 
a2aafbdb1dd8: Pull complete 
39f3a9fb96b3: Pull complete 
fcfc553e0487: Pull complete 
4e7480d759dc: Pull complete 
f9fb561be7b3: Pull complete 
a187f194aaec: Pull complete 
5b511366ba66: Pull complete 
e06d1c7f2efa: Pull complete 
c2a748dee0e5: Pull complete 
bd10f4c05439: Pull complete 
542039455a52: Pull complete 
2bf467c2ff7e: Pull complete 
bf4dd2bb5573: Pull complete 
25990aabf01f: Pull complete 
ef12d333c41b: Pull complete 
fcd5eb5af659: Pull complete 
54b5491e8f99: Pull complete 
70c10295a444: Pull complete 
b241586ee6d1: Pull complete 
8bedb2491317: Pull complete 
63d62dee1117: Pull complete 
Digest: sha256:7a8ac004eaaea573529b32be78494030882169fa423278f5261e8d88664a16ac
Status: Downloaded newer image for 127.0.0.1:5001/test-image:1

it works fine as expected.

  • However the similar is not working as expected when I configured, zot with ECR as upstream server

zot configuration for the ECR as upstream

config.json: | 
    {
      "distSpecVersion": "1.1.0",
      "storage": {
        "rootDirectory": "/tmp/zot",
        "dedupe": false,
        "storageDriver": {
          "name": "s3",
          "region": "ap-south-1",
          "bucket": "zot-test",
          "rootdirectory": "/registry",
          "secure": true,
          "skipverify": false
        }
      },
      "http": {
        "address": "0.0.0.0",
        "port": "5000"
      },
      "log": {
        "level": "debug"
      },
      "extensions": {
        "sync": {
          "credentialsFile": "",
          "DownloadDir": "/tmp/zot-s3",
          "registries": [
            {
              "urls": [
                "https://accountid.dkr.ecr.us-east-1.amazonaws.com"
              ],
              "onDemand": true,
              "maxRetries": 5,
              "retryDelay": "2m",
              "credentialHelper": "ecr"
            }
          ]
        }
      }
    }

Trying out on-demand sync with ECR as upstream registry

skopeo inspect docker://zot-aps1-dev.ia55.net/test-image:1542762016

FATA[0006] Error parsing image name "docker://zot-aps1-dev.ia55.net/test-image:1542762016": Error reading manifest 1542762016 in zot-aps1-dev.ia55.net/test-image: name unknown: repository name not known to registry

docker pull zot-aps1-dev.ia55.net/gitlab/arcesium/internal/valtech/pricing-engine:1542762016

Error response from daemon: repository zot-reg.net/gitlab/arcesium/internal/valtech/pricing-engine not found: name unknown: repository name not known to registry

Relevant zot error logs

{"level":"info","module":"http","component":"session","clientIP":"100.80.25.126:25093","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept-Encoding":["gzip"],"Docker-Distribution-Api-Version":["registry/2.0"],"User-Agent":["containers/5.10.5 (github.com/containers/image)"],"X-Amzn-Trace-Id":["Root=1-67a31495-09ce24fe153988771fab628f"],"X-Forwarded-For":["10.12.121.138"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"goroutine":226402,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T07:34:45.132658617Z","message":"HTTP API"}
{"level":"info","repository":"test-image","reference":"1542762016","goroutine":226404,"caller":"zotregistry.dev/zot/pkg/api/routes.go:2089","time":"2025-02-05T07:34:45.747700385Z","message":"trying to get updated image by syncing on demand"}
{"level":"info","goroutine":226406,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:574","time":"2025-02-05T07:34:45.747735269Z","message":"getting available client"}
{"level":"info","url":"674283286888.dkr.ecr.us-east-1.amazonaws.com","goroutine":226406,"caller":"zotregistry.dev/zot/pkg/extensions/sync/ecr_credential_helper.go:178","time":"2025-02-05T07:34:46.725102514Z","message":"the credentials are valid"}
{"level":"info","remote":"https://674283286888.dkr.ecr.us-east-1.amazonaws.com","repository":"test-image","reference":"1542762016","goroutine":226406,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:376","time":"2025-02-05T07:34:46.725160802Z","message":"syncing image"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.18.173:38266","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":226465,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T07:34:49.329159815Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.18.173:38278","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":226466,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T07:34:49.329263876Z","message":"HTTP API"}
{"level":"error","error":"media type is not supported","repository":"test-image","reference":"1542762016","goroutine":226406,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:493","time":"2025-02-05T07:34:50.162986358Z","message":"couldn't get upstream image manifest details"}
{"level":"info","repo":"test-image","1542762016":"reference","err":"media type is not supported","component":"sync","goroutine":226483,"caller":"zotregistry.dev/zot/pkg/extensions/sync/on_demand.go:157","time":"2025-02-05T07:34:50.163046942Z","message":"starting routine to copy image, because of error"}
{"level":"error","error":"media type is not supported","repository":"test-image","reference":"1542762016","goroutine":226404,"caller":"zotregistry.dev/zot/pkg/api/routes.go:2093","time":"2025-02-05T07:34:50.163055063Z","message":"failed to sync image"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.18.178:62599","method":"GET","path":"/v2/test-image/manifests/1542762016","statusCode":404,"latency":"4s","bodySize":252,"headers":{"Accept":["application/vnd.oci.image.manifest.v1+json","application/vnd.docker.distribution.manifest.v2+json","application/vnd.docker.distribution.manifest.v1+prettyjws","application/vnd.docker.distribution.manifest.v1+json","application/vnd.docker.distribution.manifest.list.v2+json","application/vnd.oci.image.index.v1+json"],"Accept-Encoding":["gzip"],"Docker-Distribution-Api-Version":["registry/2.0"],"User-Agent":["containers/5.10.5 (github.com/containers/image)"],"X-Amzn-Trace-Id":["Root=1-67a31495-645f8e37737463142ab02034"],"X-Forwarded-For":["10.12.121.138"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"goroutine":226404,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T07:34:50.595460398Z","message":"HTTP API"}

still not sure, why zot fails for the OCI image index(application/vnd.oci.image.index.v1+json) only when ECR is configured as upstream.

@andaaron
Copy link
Contributor

andaaron commented Feb 5, 2025

Any chance this does not reproduce with #2903?

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 5, 2025

I haven't tried with #2903 yet. I'll check and update this thread.

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 5, 2025

with #2903, initially I observed the following error

{"level":"error","errorType":"*fmt.wrapError","repo":"gitlab/arcesium/internal/valtech/pricing-engine","reference":"1542762016","error":"failed to list tags for account.dkr.ecr.us-east-1.amazonaws.com/test:latest: request failed: unauthorized [http 403]: {\"errors\":[{\"code\":\"DENIED\",\"message\":\"User: 1738754539209992210 is not authorized to perform: ecr:ListImages on resource: arn:aws:ecr:us-east-1:account:repository/test because no resource-based policy allows the ecr:ListImages action\"}]}\n","goroutine":1315,"caller":"zotregistry.dev/zot/pkg/extensions/sync/on_demand.go:124","time":"2025-02-05T11:24:46.418035022Z","message":"sync routine: error while copying image"}

Once I added the required IAM policy in the repo, the sync works as expected.

[vanan@vanan-registry-test-1 (shared-dev.i dev) ~]$ time  docker pull zot.net/test:1542762016
Pulling from test
Digest: sha256:01163f3d0e81b5eb2e9ecbffc1a2534db4527a06008ef7bfe13085936285d3f8
Status: Image is up to date for zot.net/test:1542762016

real    1m43.641s
user    0m0.027s
sys     0m0.026s

logs

"level":"info","module":"http","component":"session","clientIP":"100.80.17.13:9573","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept-Encoding":["gzip"],"User-Agent":["docker/18.09.1 go/go1.10.6 git-commit/4c52b90 kernel/3.10.0-1160.119.1.el7.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/18.09.1 \\(linux\\))"],"X-Amzn-Trace-Id":["Root=1-67a351e8-300b27fb323da2f369d52567"],"X-Forwarded-For":["10.12.121.23"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"goroutine":10096,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T11:56:24.968595371Z","message":"HTTP API"}
{"level":"info","repository":"test","reference":"1542762016","goroutine":13591,"caller":"zotregistry.dev/zot/pkg/api/routes.go:2087","time":"2025-02-05T11:56:25.780054861Z","message":"trying to get updated image by syncing on demand"}
{"level":"info","remote":"accountid.dkr.ecr.us-east-1.amazonaws.com","repo":"test","reference":"1542762016","goroutine":13593,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:299","time":"2025-02-05T11:56:25.780124642Z","message":"sync: syncing image"}
{"level":"info","url":"674283286888.dkr.ecr.us-east-1.amazonaws.com","goroutine":13593,"caller":"zotregistry.dev/zot/pkg/extensions/sync/ecr_credential_helper.go:178","time":"2025-02-05T11:56:25.780154043Z","message":"the credentials are valid"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.25.204:44638","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":13624,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T11:56:25.886768283Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.25.204:44642","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":13557,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T11:56:25.886887836Z","message":"HTTP API"}

However, even though the images is cached in the s3. Each time it fetch's sync from the ECR, & observed following details in the logs

[vanan@vanan-registry-test-1 (shared-dev.i dev) ~]$ time sudo docker pull zot-aps1-dev.ia55.net/gitlab/arcesium/internal/valtech/pricing-engine:1542762016

1542762016: Pulling from test
Digest: sha256:01163f3d0e81b5eb2e9ecbffc1a2534db4527a06008ef7bfe13085936285d3f8
Status: Image is up to date for zot.net/test:1542762016

real    1m52.870s
user    0m0.028s
sys     0m0.026s

relevant logs

{"level":"info","module":"http","component":"session","clientIP":"100.80.2.212:38486","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":10746,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:02:37.384921965Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.2.212:38480","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":10745,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:02:37.38496502Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.28.150:10460","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept-Encoding":["gzip"],"User-Agent":["docker/18.09.1 go/go1.10.6 git-commit/4c52b90 kernel/3.10.0-1160.119.1.el7.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/18.09.1 \\(linux\\))"],"X-Amzn-Trace-Id":["Root=1-67a36171-28d8e05b1ba7a0ab2e07a64a"],"X-Forwarded-For":["10.12.121.23"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"goroutine":7278,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:02:41.453588825Z","message":"HTTP API"}
{"level":"info","repository":"test","reference":"1542762016","goroutine":10699,"caller":"zotregistry.dev/zot/pkg/api/routes.go:2087","time":"2025-02-05T13:02:42.271343287Z","message":"trying to get updated image by syncing on demand"}
{"level":"info","remote":"674283286888.dkr.ecr.us-east-1.amazonaws.com","repo":"test","reference":"1542762016","goroutine":10701,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:299","time":"2025-02-05T13:02:42.271381253Z","message":"sync: syncing image"}
{"level":"info","url":"674283286888.dkr.ecr.us-east-1.amazonaws.com","goroutine":10701,"caller":"zotregistry.dev/zot/pkg/extensions/sync/ecr_credential_helper.go:178","time":"2025-02-05T13:02:42.271401803Z","message":"the credentials are valid"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.18.173:57412","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":7308,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:02:45.499764958Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.18.173:57426","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":7292,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:02:45.499796465Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.2.212:41958","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":10805,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:02:47.38520308Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.2.212:41956","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":10804,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:02:47.385203144Z","message":"HTTP API"}
{"level":"info","repo":"test","reference":"1542762016","localDigest":"sha256:01163f3d0e81b5eb2e9ecbffc1a2534db4527a06008ef7bfe13085936285d3f8","remoteDigest":"sha256:bf49567d1fd2e0b8abc369113843cf77a2393d9e4f2202e8e966db1760d636b3","goroutine":10701,"caller":"zotregistry.dev/zot/pkg/extensions/sync/destination.go:76","time":"2025-02-05T13:02:54.109746805Z","message":"remote image digest changed, syncing again"}
{"level":"info","remote image":"account.dkr.ecr.us-east-1.amazonaws.com/test:1542762016","local image":"test:1542762016","goroutine":10701,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:394","time":"2025-02-05T13:02:54.109781727Z","message":"syncing image"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.18.173:39902","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":7344,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:02:55.50027068Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.18.173:39898","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":7343,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:02:55.500271885Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.2.212:37810","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":10955,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:02:57.385404474Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.2.212:37812","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":10956,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:02:57.385404887Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.18.173:48596","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":7382,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:03:05.499857082Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.18.173:48610","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":7367,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:03:05.49988099Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.2.212:37420","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":10992,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:03:07.388980336Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.2.212:37422","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":10991,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:03:07.388995572Z","message":"HTTP API"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.18.173:54332","method":"GET","path":"/v2/","statusCode":200,"latency":"0s","bodySize":0,"headers":{"Accept":["*/*"],"Connection":["close"],"User-Agent":["kube-probe/1.30+"]},"goroutine":741

Since for each on-demand request, Zot thinks that the "remote image digest changed" and pulls the image again, I observed that it takes more time to pull the image compared to directly accessing the ECR.

@andaaron
Copy link
Contributor

andaaron commented Feb 5, 2025

Is there something different inside the 2 manifests? Maybe the order of properties in the json dictionaries?
Theoretically we should not rewrite OCI manifests/indexes, but maybe an unmarshal/marshal got inside our codebase without us noticing.

Only docker media types would be rewritten as oci media types, but the reported issue is for an oci media type.

Since there as an update to the IAM policy, maybe the main branch implementation sync works as expected?

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 5, 2025

Since there as an update to the IAM policy, maybe the main branch implementation sync works as expected?

with v2.1.3-rc1 /main branch still I am getting the following error

docker pull zot.net/test:1542762016
Error response from daemon: repository zot.net/test:1542762016 not found

{"level":"error","error":"media type is not supported","repository":"test","reference":"1542762016","goroutine":1512,"caller":"zotregistry.dev/zot/pkg/api/routes.go:2093","time":"2025-02-05T13:59:48.911294811Z","message":"failed to sync image"}
{"level":"info","module":"http","component":"session","clientIP":"100.80.20.102:59027","method":"GET","path":test/manifests/1542762016","statusCode":404,"latency":"4s","bodySize":252,"headers":{"Accept":["application/vnd.docker.distribution.manifest.v1+prettyjws","application/json","application/vnd.oci.image.manifest.v1+json","application/vnd.oci.image.index.v1+json","application/vnd.docker.distribution.manifest.v2+json","application/vnd.docker.distribution.manifest.list.v2+json"],"Accept-Encoding":["gzip"],"User-Agent":["docker/18.09.1 go/go1.10.6 git-commit/4c52b90 kernel/3.10.0-1160.119.1.el7.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/18.09.1 \\(linux\\))"],"X-Amzn-Trace-Id":["Root=1-67a36ed0-36ef6dc2212dacc7167a75f4"],"X-Forwarded-For":["10.12.121.23"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"goroutine":1512,"caller":"zotregistry.dev/zot/pkg/api/session.go:137","time":"2025-02-05T13:59:49.358228404Z","message":"HTTP API"}

Is there something different inside the 2 manifests? Maybe the order of properties in the json dictionaries?
Theoretically we should not rewrite OCI manifests/indexes, but maybe an unmarshal/marshal got inside our codebase without us noticing.

I will try to debug further and get more details.

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 5, 2025

func (registry *DestinationRegistry) CanSkipImage(repo, tag string, digest godigest.Digest) (bool, error) {
// check image already synced
imageStore := registry.storeController.GetImageStore(repo)
_, localImageManifestDigest, _, err := imageStore.GetImageManifest(repo, tag)
https://github.com/eusebiu-constantin-petu-dbk/zot/blob/sync_regclient_2/pkg/extensions/sync/destination.go#L58

I think while checking the image mainfest, we are not passing the tag for the upstream registry. we are passing the tag in the image store. Since the tag is not being passed, it might default to the latest tag, causing a mismatch between the local digest and the upstream registry.

@andaaron
Copy link
Contributor

andaaron commented Feb 5, 2025 via email

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 6, 2025

@andaaron/ @eusebiu-constantin-petu-dbk , you can ignore this comment
#2836 (comment)
I have verified that it refers to correct image tag for the upstream as well the image in present in the local store.

@andaaron ,
digest for the image stored locally

{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:eea456504e848927b80b42427a2b466e25f7ddc226d18765912936001fda6288","size":4841},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:5a6a7e7e93c854dc0f7df8c4ee669c3ba4a30bee27362bb194ba1defbbcb1409","size":4843},{"mediaType":"application/vnd.oci.image.index.v1+json","digest":"sha256:01163f3d0e81b5eb2e9ecbffc1a2534db4527a06008ef7bfe13085936285d3f8","size":493,"annotations":{"org.opencontainers.image.ref.name":"1542762016"}}]}

However, in the ECR image index, the digest is:
sha256:4bc9139c512e40d87d25f80830627713a83db1d12f3df6fc8f0cece5dd580e2a

This indicates that the digest has not been calculated correctly for the locally stored image.

@andaaron
Copy link
Contributor

andaaron commented Feb 6, 2025

Is there something different inside the 2 manifests? Maybe the order of properties in the json dictionaries? Theoretically we should not rewrite OCI manifests/indexes, but maybe an unmarshal/marshal got inside our codebase without us noticing.

Only docker media types would be rewritten as oci media types, but the reported issue is for an oci media type.

I can't check the content of the files since I don't have access to that image. Can you please check what is different in the remote index vs the local index content?

L.E. what is the input over which the hash "sha256:01163f3d0e81b5eb2e9ecbffc1a2534db4527a06008ef7bfe13085936285d3f8" was generated. versus the one for "sha256:4bc9139c512e40d87d25f80830627713a83db1d12f3df6fc8f0cece5dd580e2a".

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 6, 2025

I tried pulling the image from both the ECR and the Zot registry to the local disk and performed a diff.
I observed that the generated manifest in Zot has a difference.

  • copy zot image to local disk
    skopeo copy --all docker://zot-.net/test:1542762016 dir:///tmp/pricing-engine-zot-all
  • copy ecr image to local disk
    skopeo copy --all docker://accountid.dkr.ecr.us-east-1.amazonaws.com/test:1542762016

Files content/blob looks same
Image

I found following diff for the manfiest between the ecr and the zot

diff /tmp/pricing-engine-ecr-all/ /tmp/pricing-engine-zot-all/
diff '--color=auto' /tmp/pricing-engine-ecr-all/manifest.json /tmp/pricing-engine-zot-all/manifest.json
1,24c1
< {
<   "schemaVersion": 2,
<   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
<   "manifests": [
<     {
<       "mediaType": "application/vnd.oci.image.manifest.v1+json",
<       "size": 4841,
<       "digest": "sha256:eea456504e848927b80b42427a2b466e25f7ddc226d18765912936001fda6288",
<       "platform": {
<         "architecture": "amd64",
<         "os": "linux"
<       }
<     },
<     {
<       "mediaType": "application/vnd.oci.image.manifest.v1+json",
<       "size": 4843,
<       "digest": "sha256:5a6a7e7e93c854dc0f7df8c4ee669c3ba4a30bee27362bb194ba1defbbcb1409",
<       "platform": {
<         "architecture": "arm64",
<         "os": "linux"
<       }
<     }
<   ]
< }
\ No newline at end of file
---
> {"schemaVersion":2,"mediaType":"application/vnd.oci.image.index.v1+json","manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:eea456504e848927b80b42427a2b466e25f7ddc226d18765912936001fda6288","size":4841,"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:5a6a7e7e93c854dc0f7df8c4ee669c3ba4a30bee27362bb194ba1defbbcb1409","size":4843,"platform":{"architecture":"arm64","os":"linux"}}]}
\ No newline at end of file

Manifest digest

> skopeo manifest-digest /tmp/pricing-engine-ecr-all/manifest.json
sha256:4bc9139c512e40d87d25f80830627713a83db1d12f3df6fc8f0cece5dd580e2a
 ~>  skopeo manifest-digest /tmp/pricing-engine-zot-all/manifest.json
sha256:01163f3d0e81b5eb2e9ecbffc1a2534db4527a06008ef7bfe13085936285d3f8
) ~>

@andaaron
Copy link
Contributor

andaaron commented Feb 6, 2025

Question is why is that a "application/vnd.docker.distribution.manifest.list.v2+json? We convert this media type to and OCI image index.

@rchincha
Copy link
Contributor

rchincha commented Feb 6, 2025

There is "docker image index" containing "OCI image manifests" in ecr vs all OCI in zot (as expected)?

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 6, 2025

In our build pipeline, we use the manifest-tool to create a multi-architecture image, which is then pushed to ECR.
I will review those configurations in detail and get back to you

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 6, 2025

I used the following command to create an OCI image index and pushed it to ECR. Even though I explicitly specified the OCI format, the resulting manifest in ECR is stored as a Docker manifest list (application/vnd.docker.distribution.manifest.list.v2+json).

vanan@vanan-zot-1 (shared-dev.i) ~> cat manifest.yaml
image: ACCOUNTID.dkr.ecr.us-east-1.amazonaws.com/test-zot:oci-test
manifests:
  - image: ACCOUNTID.dkr.ecr.us-east-1.amazonaws.com/test-zot@sha256:e4a64072c73d71ecc5c8aa7bea1b3462930d599b692d77bfe51bea7ec21de90f
    platform:
      architecture: amd64
      os: linux
  - image: ACCOUNTID.dkr.ecr.us-east-1.amazonaws.com/test-zot@sha256:d32e2f8a99c97bce4741f495eb5fedda2975744bb4331002f18550c7fc5f7e79
    platform:
      architecture: arm64
      os: linux

Pushed the manifest using:

vanan@vanan-zot-1 (shared-dev.i) ~> sudo manifest-tool push from-spec manifest.yaml --type oci
Digest: sha256:fd3d587e64454a43de990e1fc83c1131d48443a67a78d228f4ca365efdbf9d64 665

However, inspecting the manifest in ECR reveals that AWS ECR stores it as a Docker manifest list instead of an OCI image index:

manifest-tool inspect ACCOUNTID.dkr.ecr.us-east-1.amazonaws.com/test-zot:oci-test

Name:   ACCOUNTID.dkr.ecr.us-east-1.amazonaws.com/test-zot:oci-test (Type: application/vnd.docker.distribution.manifest.list.v2+json)
Digest: sha256:fd3d587e64454a43de990e1fc83c1131d48443a67a78d228f4ca365efdbf9d64
 * Contains 2 manifest references (2 images, 0 attestation):
[1]     Type: application/vnd.oci.image.manifest.v1+json
[1]   Digest: sha256:e4a64072c73d71ecc5c8aa7bea1b3462930d599b692d77bfe51bea7ec21de90f
[1]   Length: 2602
[1] Platform:
[1]    -      OS: linux
[1]    -    Arch: amd64
[1] # Layers: 15
     layer 01: digest = sha256:38a8310d387e375e0ec6fabe047a9149e8eb214073db9f461fee6251fd936a75
     -- 
     layer 15: digest = sha256:b4e96f2acd28a06b2ed98f01b035a35cfd2abea6bb73d02efdfde3f202d90823
                 type = application/vnd.oci.image.layer.v1.tar+gzip

[2]     Type: application/vnd.oci.image.manifest.v1+json
[2]   Digest: sha256:d32e2f8a99c97bce4741f495eb5fedda2975744bb4331002f18550c7fc5f7e79
[2]   Length: 2602
[2] Platform:
[2]    -      OS: linux
[2]    -    Arch: arm64
[2] # Layers: 15
     layer 01: digest = sha256:cb8611c9fe5154550f45e284cf977cda4e2b2fee3478552eee31d84be3c95003
                 type = application/vnd.oci.image.layer.v1.tar+gzip
 -- 
     layer 15: digest = sha256:b2fee7538136b7246b4d49a487d772e57a908b2728e2f118b8287643e7fdaea8
                 type = application/vnd.oci.image.layer.v1.tar+gzip

https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-manifest-formats.html

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 6, 2025

@andaaron / @rchincha – Looking for your suggestions on this.
For ECR, can we skip checking the remote manifest digest and instead:
Sync the image only if it is not available locally?
I understand this may not be the ideal approach, so I’d appreciate your insights on the best way to handle this.

@andaaron
Copy link
Contributor

andaaron commented Feb 6, 2025

Hmm, can you try manifest-tool push --type oci from-spec manifest.yaml? Different order of parameters.

Log term we were discussing and this is what we would want to do: #2903 (comment) (probably in a later PR).
What you suggested was an older implementation of ours, and it was changed because "latest" was not getting updated :)

@tamilhce
Copy link
Contributor Author

tamilhce commented Feb 6, 2025

Hmm, can you try running manifest-tool push --type oci from-spec manifest.yaml with a different parameter order?

Thanks, @andaaron! It works now. 😊

Name:   ACCOUNTID.dkr.ecr.us-east-1.amazonaws.com/test-zot:oci-test (Type: application/vnd.oci.image.index.v1+json)  
Digest: sha256:495255bbacb980e8511b3dd0024491eed0cbba6331ffdbe9a13d7f855ba63f92  
 * Contains 2 manifest references (2 images, 0 attestations):  
[1]     Type: application/vnd.oci.image.manifest.v1+json  
[1]   Digest: sha256:e4a64072c73d71ecc5c8aa7bea1b3462930d599b692d77bfe51bea7ec21de90f  
[1]   Length: 2602  
[1] Platform:  
[1]    - OS: linux  
[1]    - Arch: amd64  

I can now proceed further and update my pipeline to create new images using the OCI image index. However, we have a large number of existing repositories and images that need updating, which isn't feasible.

I’d like to work on this feature. yo can assign it to me.

@andaaron
Copy link
Contributor

andaaron commented Feb 6, 2025

I think @eusebiu-constantin-petu-dbk already has some code for it, but it depends on his existing pr.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting-answers rm-external Roadmap item submitted by non-maintainers
Projects
None yet
Development

No branches or pull requests

3 participants