mirror of
https://github.com/kvcache-ai/AgentENV.git
synced 2026-11-05 01:17:36 +00:00
[GH-ISSUE #378] [Design Proposal] Repository-published OverlayBD images #95
Labels
No labels
bug
documentation
enhancement
enhancement
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/AgentENV#95
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @Primary33 on GitHub (Oct 13, 2026).
Original GitHub issue: https://github.com/kvcache-ai/AgentENV/issues/378
Affected component
OverlayBD / image resolution
Problem statement
AgentENV can start sandboxes from external OCI images and from templates, but it has no reusable, repository-owned image artifact. Today an image built through BuildKit is either turned into a template (which also creates a snapshot record) or stays in one node's conversion cache. Cache eviction can remove it, and other nodes cannot resolve it.
Multi-service workloads (for example Compose projects, #348) and plain image builds need an artifact that:
This issue documents the image model implemented in #347 (build, publication, and tag creation and resolution) and #359 (catalog, and tag listing and deletion), so reviewers and users can agree on its semantics before merge. Image tags were added following the review discussion in this issue.
Use case
aenv build --image ./appbuilds a Dockerfile remotely and prints asha256:...reference. The reference can be used in a sandboximagefield on any node that shares the repository.aenv build --image ./app --tag app:v1also points the tagapp:v1at the new image.aenv start --cold aenv/app:v1, a sandboximagefield, or a Composeimage:field can then use the tag. Rebuilding and re-tagging moves new launches to the new image without editing any reference.Current behavior and workarounds
sha256:image reference has no repository-backed meaning. Resolution goes through registry or node-local conversion caches.Desired behavior
ready, then all layers and the image description are durable in the shared repository, and the reported digest resolves on any compatible node.aenv/name:tag, then it starts from the digest the tag points to at that moment, and the sandbox and its snapshots record only that digest.Proposed approach
Image identity and storage format
A published image is a canonical JSON description (
PublishedImage,src/image/mod.rs):catalog/images/{digest}.json. Layer data uses the same content-addressed managed-layer storage as snapshots.Repository usage
Since #370 the repository only stores documents and blobs, so images add no repository or backend methods. They use:
DocumentKey::Image(digest)catalog/images/{digest}.json: one verified descriptionDocumentKey::ImageTag(tag)catalog/image-tags/{name}:{tag}.json: the digest a tag points toDocumentCollection::Images/DocumentCollection::ImageTagslist_documents(#359)snapshot::store::store_volume_layerssnapshot::resolver::materialize_volume_backingImageCatalog(src/image/catalog.rs) implements image and tag put/get/list/delete once for everyRepositoryon top ofget/put/delete/list_documents, likeSnapshotCatalogandVolumeCatalog, so POSIX and OSS behave the same. Images and volumes share layer publication, while their catalog records and lifecycles stay independent. Digest validation lives incrate::digestandImageTagincrate::types, so the repository module still does not depend on image code.Resolution
ImageResolvertreats a trimmed reference starting withaenv/as an image tag and a trimmedsha256:reference as a published image:aenv/name[:tag], read the tag document and continue with its digest (NotFoundif the tag is absent).NotFoundif absent).Because step 2 runs on every resolution, deletion blocks new launches even on a warm node. The resolved reference is always the digest, so node caches are keyed by digest and a moved tag is never served from a stale cache entry.
Build lifecycle (
/images/builds, #347)POST /images/buildsbuildIDand the BuildKitimageName, plus anx-agentenv-build-idheader for gateway routingWS /images/builds/{id}/builderGET /images/builds/{id}waiting/building/ready(withimageDigest) /errorDELETE /images/builds/{id}put_image, then journalReady{digest}.image/{id}. They survive worker cleanup and server restart, and their gateway routing is restored at startup./images/builds/{id}[/builder]by path.aenv build --image CONTEXTprints only the digest on stdout (diagnostics go to stderr) and deletes the build record when it finishes.Catalog (
/images, #359)GET /images?limit=&nextToken=GET /images/{digest}DELETE /images/{digest}204even if absent). Removes the description, not the layers or the tags that point to itCatalog and tag operations can run on any node using the repository. Build status still routes to the build node.
Image tags (
/images/tags, #347 and #359)name:tagpointer to one published image. The name uses lowercase letters and digits joined by single.,_, or-. The tag starts with a letter, digit, or_and continues with letters, digits,.,_, or-. Each is at most 128 characters. An omitted tag meanslatest, and tags are stored in canonicalname:tagform.aenv/name[:tag]wherever they acceptsha256:...: cold sandboxes, attached drives, volumes created from an image, template base images, and Compose services. The reference is a valid OCI short name, so tools that validate image names accept it. Short names underaenv/always mean tags; an OCI image in a registry'saenvnamespace needs its full name, such asdocker.io/aenv/app:v1.PUT /images/tags/{tag}(#347){"imageDigest": "sha256:..."}. Creates the tag or moves it. Returns 404 if the image is not publishedGET /images/tags/{tag}(#347)GET /images/tags?limit=&nextToken=(#359)name:tag, limit 1-100, with the same cursor rules asGET /imagesDELETE /images/tags/{tag}(#359)204even if absent). Never deletes the imageDELETE /images/{digest}leaves tags that point to the image in place. Resolving such a tag fails withNotFounduntil the tag is moved or deleted, and it still appears in listings. Tagging is not atomic with image deletion, so a concurrent delete can also leave a dangling tag.aenv build --image CONTEXT --tag NAME[:TAG](repeatable) validates tags before the build starts, prints the digest on stdout as before, then tags it and reportsTagged aenv/...on stderr. If a tag request fails, the command exits non-zero after the digest has been printed.--tagcannot be combined with template or Compose builds.aenv build --composekeeps writing digests into the generated Compose file, so built projects stay pinned. Hand-written Compose files may useaenv/references.Local cache ownership
Only files owned by the node's commit store count as local hard commits (
src/image/cache/graph.rs). Repository-owned layers referenced by materialized configs are not charged to, or collected by, local capacity eviction. A local copy of the same layer digest from an OCI conversion is still evictable.Compatibility and operational impact
API/config changes:
imagesAPI tag:/images/builds*,/images,/images/{digest},/images/tags,/images/tags/{tag}. No new config keys; the image API uses the existingsnapshot.repository_backend.sha256:sandboximagenow means a published image description, not an OCI manifest digest.aenv/now name image tags. They previously resolved through the search registries (for exampledocker.io/aenv/...). Fully qualified references, includingdocker.io/aenv/..., are unchanged.aenv build --image --tag.Snapshot or storage format changes:
catalog/images/andcatalog/image-tags/. POSIX lock files (*.lock) sit beside the documents. Snapshot, volume, and existing layer formats are unchanged.New host/runtime requirements:
Upgrade and rollback considerations:
--imageand--tag.catalog/images/andcatalog/image-tags/, and sandboxes that refer to published digests oraenv/tags cannot be resolved.Open questions
--opt platform=linux/amd64to buildctl. Publication, however, records the host architecture, and resolution requires it to match the host. On an arm64 host this produces amd64 layers labelledarm64.Alternatives considered
--image-repository).name:tagreferences for tags. Every such string is already a valid OCI reference (for exampledocker.io/library/name:tag). Checking the repository first would let a tag shadow a registry image and add a repository read to every registry launch. Theaenv/prefix reserves only one short-name namespace and never falls back to a registry.aenv://name:tagscheme. It cannot collide with any OCI reference, but it is not a valid OCI reference, so tools that validate image names reject it.name:tagmatchesdocker build -tand Composeimage:usage and keeps several versions under one name.Non-goals
team/app), immutable or protected tags, and listing an image's tags inGET /images.Contribution
I can implement it
Implemented in #347 (image build and publication; tag creation and resolution) and #359 (image catalog; tag listing and deletion).
Pre-submission checklist
@yingdi-shan commented on GitHub (Oct 13, 2026):
Maybe we should assign a tag/alias for each of our image?
@Primary33 commented on GitHub (Oct 14, 2026):
Thanks @yingdi-shan, good suggestion. #347 and #359 now support image tags (
aenv/name:tag), and I've updated the proposal above. See Proposed approach → Image tags for the design.