fix: mismatched mediaType error when push image build with warmed bas…
Fixes #2423 #2713 #2883
Description
given base image ubuntu:22.04 with oci format:
$ crane manifest ubuntu@sha256:0eb0f877e1c869a300c442c41120e778db7161419244ee5cbc6fa5f134e74736 | jq
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 2297,
"digest": "sha256:8a3cdc4d1ad3e314a91f76b7b99eed443f2152e3a9bf33e46669b31d094be443"
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 29534055,
"digest": "sha256:3713021b02770a720dea9b54c03d0ed83e03a2ef5dce2898c56a327fee9a8bca"
}
]
}
when warmup cache option is turned on, kaniko build will load base image from tarball using github.com/google/go-containerregistry/pkg/v1/tarball.ImageFromPath func and return docker format v1.Image
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 2297,
"digest": "sha256:8a3cdc4d1ad3e314a91f76b7b99eed443f2152e3a9bf33e46669b31d094be443"
},
"layers": [{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 29534055,
"digest": "sha256:3713021b02770a720dea9b54c03d0ed83e03a2ef5dce2898c56a327fee9a8bca"
}]
}
However, kaniko will override the Manifest method, prioritizing the content parsed from the manifest file. This will cause the issue mentioned in #2423 when the base image is in oci format.
// pkg/cache/cache.go
func (c *cachedImage) Manifest() (*v1.Manifest, error) {
if c.mfst == nil {
return c.Image.Manifest()
}
return c.mfst, nil
}
After kaniko build with warmup cache done, push image will get error:
error pushing image: failed to push to destination xxx/xxx:latest: PUT https://index.docker.io/v2/xxx/xxx/manifests/latest: MANIFEST_INVALID: manifest invalid; mediaType in manifest should be 'application/vnd.docker.distribution.manifest.v2+json' not 'application/vnd.oci.image.manifest.v1+json'
If add --oci-layout-path option, the oci-layout will looks like follow which contain different mediaType.
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 407,
"digest": "sha256:5c8a7c5d81ce01fa001bad84905be012c3187fe9efdf937055b5c95d932edb19"
}
]
}
How to fix
option 1)
[!IMPORTANT] Depend on https://github.com/google/go-containerregistry/pull/1969
add func OCIImageFromPath to github.com/google/go-containerregistry/pkg/v1/tarball and return v1.Image with OCI mediaType(this PR's choice)
option2)
Update cachedImage's func Manifest in pkg/cache/cache.go and return tabball's manifest by default. The result is that when kaniko uses warmup cache, even if the base image is in OCI format, the resulting target image is in Docker format.
func (c *cachedImage) Manifest() (*v1.Manifest, error) {
if c.mfst == nil {
return c.Image.Manifest()
}
return c.mfst, nil
}
// ->
func (c *cachedImage) Manifest() (*v1.Manifest, error) {
mfst, err := c.Image.Manifest()
if mfst != nil {
return mfst, err
}
return c.mfst, nil
}
Submitter Checklist
These are the criteria that every PR should meet, please check them off as you review them:
- [ ] Includes unit tests
- [ ] Adds integration tests if needed.
See the contribution guide for more details.
Reviewer Notes
- [ ] The code flow looks good.
- [ ] Unit tests and or integration tests added.
Release Notes
none