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

feat: add support for docker images #2714

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

rchincha
Copy link
Contributor

@rchincha rchincha commented Oct 9, 2024

Issue #724

What type of PR is this?

Which issue does this PR fix:

What does this PR do / Why do we need it:

If an issue # is not available please add repro steps and logs showing the issue:

Testing done on this change:

Automation added to e2e:

Will this break upgrades or downgrades?

Does this PR introduce any user-facing change?:


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Copy link

codecov bot commented Oct 9, 2024

Codecov Report

Attention: Patch coverage is 35.13514% with 24 lines in your changes missing coverage. Please review.

Project coverage is 92.01%. Comparing base (da6bd56) to head (b270eff).

Files with missing lines Patch % Lines
pkg/compat/compat.go 0.00% 19 Missing ⚠️
pkg/storage/common/common.go 37.50% 4 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2714      +/-   ##
==========================================
- Coverage   92.08%   92.01%   -0.08%     
==========================================
  Files         169      170       +1     
  Lines       30038    30066      +28     
==========================================
+ Hits        27660    27664       +4     
- Misses       1759     1782      +23     
- Partials      619      620       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@ChristianCiach
Copy link

Thank you for considering to support docker images! This looks very promising!

As described in #724 (comment), we are using imgpkg to store arbitrary files in a registry. I've built this PR locally and this seems to work now:

$ echo "hello" > test.txt

$ imgpkg push -i localhost:8080/myimgpkg:v1.0.0 -f test.txt --registry-insecure
file: test.txt
Pushed 'localhost:8080/myimgpkg@sha256:1ade68269f776e0dc0de49f527509cc3665ce2c9f2c4f6fb64a19117154b6bc3'
Succeeded

$ imgpkg pull -i localhost:8080/myimgpkg:v1.0.0 -o downloads
Pulling image 'localhost:8080/myimgpkg@sha256:1ade68269f776e0dc0de49f527509cc3665ce2c9f2c4f6fb64a19117154b6bc3'
Extracting layer 'sha256:04265ef25b5baf9caab409c3ae3deb9cd57338794bfcb0431d6e6f01c6458dbf' (1/1)

Succeeded

$ cat downloads/test.txt 
hello

It's a bit surprising that the pushed artifact isn't listed in the Zot-UI. Even after pushing the artifact, the UI still shows No images. Other than this, this seems to work fine!

@ChristianCiach
Copy link

ChristianCiach commented Oct 16, 2024

Attaching and downloading/verifying cosign-attestations (see #724 (comment)) works fine:

$ skopeo copy docker://docker.io/library/redis:7.4.1 docker://localhost:8080/myredis/redis:7.4.1 --dest-tls-verify=false
Getting image source signatures
Copying blob 99f3f5284f55 done   | 
Copying blob 302e3ee49805 done   | 
Copying blob e4edbcee329b done   | 
Copying blob 4b3c79aadafc done   | 
Copying blob 378d889b37dd done   | 
Copying blob c78d46bd3323 done   | 
Copying blob 4f4fb700ef54 done   | 
Copying blob 1f4a511d4985 done   | 
Copying config 3690036745 done   | 
Writing manifest to image destination

$ cosign generate-key-pair
Enter password for private key: 
Enter password for private key again: 
Private key written to cosign.key
Public key written to cosign.pub

$ trivy image --format cyclonedx --output sbom.json localhost:8080/myredis/redis:7.4.1
2024-10-16T12:41:16+02:00	INFO	"--format cyclonedx" disables security scanning. Specify "--scanners vuln" explicitly if you want to include vulnerabilities in the CycloneDX report.
2024-10-16T12:41:17+02:00	INFO	Detected OS	family="debian" version="12.7"
2024-10-16T12:41:17+02:00	INFO	Number of language-specific files	num=1


$ cosign attest --tlog-upload=false --replace --predicate sbom.json --type cyclonedx --key cosign.key  localhost:8080/myredis/redis:7.4.1 --insecure-skip-verify
WARNING: Image reference localhost:8080/myredis/redis:7.4.1 uses a tag, not a digest, to identify the image to sign.
    This can lead you to sign a different image than the intended one. Please use a
    digest (example.com/ubuntu@sha256:abc123...) rather than tag
    (example.com/ubuntu:latest) for the input to cosign. The ability to refer to
    images by tag will be removed in a future release.

Enter password for private key: 
Using payload from: sbom.json

$ cosign verify-attestation localhost:8080/myredis/redis:7.4.1 --key cosign.pub --type cyclonedx --private-infrastructure

Verification for localhost:8080/myredis/redis:7.4.1 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key

Or by digest:

$ skopeo copy docker://docker.io/library/redis:7.4.1 docker://localhost:8080/myredis/redis:7.4.1 --dest-tls-verify=false --digestfile digest.txt

$ cosign attest --tlog-upload=false --replace --predicate sbom.json --type cyclonedx --key cosign.key  localhost:8080/myredis/redis@$(cat digest.txt) --insecure-skip-verify

$ cosign verify-attestation localhost:8080/myredis/redis@$(cat digest.txt) --key cosign.pub --type cyclonedx --private-infrastructure

Again, the attestation artifacts are not shown in the UI, unfortunately. But everything else seems to work!

@sudo-bmitch
Copy link

sudo-bmitch commented Oct 16, 2024

Docker manifest lists (media type application/vnd.docker.distribution.manifest.list.v2+json) need to be supported too:

$ regctl image copy alpine localhost:5003/library/alpine
WARN[0006] Failed to push manifest                       err="failed to put manifest localhost:5003/library/alpine:latest: request failed: unexpected http status code: Unsupported Media Type [http 415]: {\"errors\":[{\"code\":\"MANIFEST_INVALID\",\"message\":\"manifest invalid\",\"detail\":{\"description\":\"During upload, manifests undergo several checks ensuring validity. If those checks fail, this error MAY be returned, unless a more specific error is included. The detail will contain information the failed validation.\",\"mediaType\":\"application/vnd.docker.distribution.manifest.list.v2+json\"}}]}" target="localhost:5003/library/alpine"
Manifests: 8/9 | Blobs: 28.060MB copied, 0.000B skipped | Elapsed: 6s
failed to put manifest localhost:5003/library/alpine:latest: request failed: unexpected http status code: Unsupported Media Type [http 415]: {"errors":[{"code":"MANIFEST_INVALID","message":"manifest invalid","detail":{"description":"During upload, manifests undergo several checks ensuring validity. If those checks fail, this error MAY be returned, unless a more specific error is included. The detail will contain information the failed validation.","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json"}}]}

@rchincha
Copy link
Contributor Author

rchincha commented Oct 16, 2024

@ChristianCiach

It's a bit surprising that the pushed artifact isn't listed in the Zot-UI. Even after pushing the artifact, the UI still shows No images. Other than this, this seems to work fine!

^ feature-ask-creep as cautioned ...

"Properly" supporting this means UI changes, sync/mirror changes, cve scan changes, scrub changes, etc ...

So now our turn, when can we expect these additional PRs from the community :)

@rchamarthy rchamarthy self-requested a review October 16, 2024 21:14
@rchincha rchincha force-pushed the docker branch 2 times, most recently from 505af16 to e6f5117 Compare October 16, 2024 21:22
@rchincha
Copy link
Contributor Author

Docker manifest lists (media type application/vnd.docker.distribution.manifest.list.v2+json) need to be supported too:

PR updated

@rchincha
Copy link
Contributor Author

rchincha commented Oct 17, 2024

Just to be clear on expectations ...

The plan is to initially include a config variable to support docker images for storage alone.
At least so you have a path to move to the OCI world when ready.
Note that UI and other features may not be compatible with this, yet.

@dkowis
Copy link

dkowis commented Oct 20, 2024

https://github.com/dkowis/zot-builder

I built the containers here using the same action as the regular zot repo. I haven't had a chance to try it yet, but I will soon. They're built to include this pull request.

I am not quite skilled enough to tell it how to run every update to the pr

@dkowis
Copy link

dkowis commented Oct 21, 2024

❯ docker push 10.10.220.122:5000/kowis/wordpress-container:latest                                                                                                                                                       (base)
The push refers to repository [10.10.220.122:5000/kowis/wordpress-container]
ae4bcbffe5fd: Pushed
accafdfb8b6b: Pushed
c0aef9492dc9: Pushed
016e0aa6ea40: Pushed
288e20f97e73: Pushed
942024bbfeb5: Pushed
715549c2b876: Pushed
d6ba68a054ab: Pushed
1526b25b30db: Pushed
9e365279cf2d: Pushed
94240d5234b3: Pushed
cd489fe24bc2: Pushed
f45bcfd0fccd: Pushed
2d73535e9e48: Pushed
d8ad9f2f23c6: Pushed
96b32d718052: Pushed
0d6988e565c0: Pushed
cc85edc5b0c7: Pushed
c9df3535113d: Pushed
34f5154c7045: Pushed
dfd6300bd525: Pushed
60f0b6ccdbac: Pushed
599a2026a8f6: Pushed
8d853c8add5d: Pushed
latest: digest: sha256:c3f34f85b30621151645348b34a52204303a7daf5cd2b2906ab810018d6c867e size: 5340

I have pushed a docker buildx built container into zot.

I can confirm that it doesn't show up in the UI anywhere, but a pull works just fine.

@rchincha
Copy link
Contributor Author

rchincha commented Oct 21, 2024

{
    "distSpecVersion": "1.1.0",
    "storage": {
        "rootDirectory": "/data/hdd/rchincha/tmp/zot"
    },
    "http": {
        "address": "0.0.0.0",
        "port": "8080",
        "compat": ["docker2s2"]
    },
    "log": {
        "level": "debug"
    }
}

^ a new "compat" config field is now added
"docker2s2" = Docker Manifest v2 Schema v2

@rchincha rchincha force-pushed the docker branch 4 times, most recently from 54be4e4 to 9a64b2d Compare October 22, 2024 21:03
Issue project-zot#724

A new config section under "HTTP" called "Compat" is added which
currently takes a list of possible compatible legacy media-types.

Only "docker2s2" (Docker Manifest V2 Schema V2) is currently supported.

Signed-off-by: Ramkumar Chinchani <[email protected]>
@rchincha
Copy link
Contributor Author

@andaaron let's merge this so community can at least start using zot as a docker registry.
UI changes can come in another PR. Thoughts?

Copy link
Contributor

@andaaron andaaron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The storage package update is not complete. There is logic there going recursively from index to index to manifests to blobs.

Theoretically we could unmarshal the docker media types into oci structs for the purpose of handling GC and dedupe.

@@ -62,10 +65,10 @@ func GetManifestDescByReference(index ispec.Index, reference string) (ispec.Desc
}

func ValidateManifest(imgStore storageTypes.ImageStore, repo, reference, mediaType string, body []byte,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we validate the docker manifest the same as ispec.MediaTypeImageManifest and the docker image list as a ispec.MediaTypeImageIndex in this function?

Theoretically we we should be able to unmarshal them, and use the references for dedupe, gc, and other essential features.

return true
}
}

return mediaType == ispec.MediaTypeImageIndex ||
mediaType == ispec.MediaTypeImageManifest
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given my other comment on this file is applied, the IsNonDistributable function should be modified to include the docker media types for layers.

}
}

func (mc *MediaCompatibility) UnmarshalJSON(data []byte) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this code used? It has 0 coverage.

DockerManifestV2SchemaV2 = "docker2s2"
)

func (mc MediaCompatibility) MarshalJSON() ([]byte, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this code used? It has 0 coverage.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should have been updated to handle the docker media types when writing to the repo index.
Same as the other methods reading/updating the repo index.

I am thinking in particular about the docker manifest list, and that it needs to be unmarshaled into an oci Index struct in order to handle the references to the manifests inside. There are some recursive functions used.
That code is in pkg/storage/common/common.go but imported here.
This is just 1 example, there may be other such cases where we need to unmarshal the docker manifests/manifest lists.

There may be changes needed here and in pkg/storage/common/common.go

FROM public.ecr.aws/docker/library/busybox:latest
RUN echo "hello world" > /testfile
EOF
docker build -f Dockerfile . -t localhost:${zot_port}/test
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make sure docker mediatypes are produced? The docker command may be an alias for some other tool, such as podman.

@andaaron
Copy link
Contributor

andaaron commented Oct 23, 2024

@andaaron let's merge this so community can at least start using zot as a docker registry. UI changes can come in another PR. Thoughts?

I think we can handle the search / CVE / UI changes in a separate PR, but the storage (GC/dedupe/scrub) changes should be included in this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants