Skip to content

Conversation

@ndeloof
Copy link
Contributor

@ndeloof ndeloof commented Oct 1, 2025

What I did

Introduce option to publish a Compose application as compose.yaml artifact + references to images

In addition to the compose.yaml file(s) stored in OCI artifact, command creates an OCI index for all images used by the compose application. This index is linked to compose artifact using an OCI Subject

flowchart TD
    TAG --> A
    A[Compose OCI Artifact] -->|layer| B(compose.yaml)
    A -->|layer| C(image-digests.yaml)
    I[Index] -->|Subject| A
    I -->|Manifest| R1[image]
    I -->|Manifest| R2[image]
Loading
# Publish compose application
#
$ docker compose --progress=plain publish --app nicolasdeloof582/bidule:chose
...
 nicolasdeloof582/bidule:chose published 

# Search for referrers for published OCI artifact
#
$ regctl artifact list nicolasdeloof582/bidule:chose
Subject:                        docker.io/nicolasdeloof582/bidule@sha256:1eb94ed3a7261bef470b21af724e0b925df9986d4a4aa1db052c35c154361da4
                                
Referrers:                      
                                
  Name:                         docker.io/nicolasdeloof582/bidule@sha256:f335c03f80b2915a4d978e4e9ea315058ff170db7e457a97b851eceea8e83622
  Digest:                       sha256:f335c03f80b2915a4d978e4e9ea315058ff170db7e457a97b851eceea8e83622
  MediaType:                    application/vnd.oci.image.index.v1+json
  Annotations:                  
    com.docker.compose.version: 2.39.4

# Inspect the referrer manifest
#
$ regctl manifest get docker.io/nicolasdeloof582/bidule@sha256:f335c03f80b2915a4d978e4e9ea315058ff170db7e457a97b851eceea8e83622
time=2025-10-01T17:22:45.360+02:00 level=WARN msg="Changing login user for registry" orig=nicolasdeloof582 new=ndeloof host=docker.io
Name:                                            docker.io/nicolasdeloof582/bidule@sha256:f335c03f80b2915a4d978e4e9ea315058ff170db7e457a97b851eceea8e83622
MediaType:                                       application/vnd.oci.image.index.v1+json
Digest:                                          sha256:f335c03f80b2915a4d978e4e9ea315058ff170db7e457a97b851eceea8e83622
Annotations:                                     
  com.docker.compose.version:                    2.39.4
                                                 
Manifests:                                       
                                                 
  Name:                                          docker.io/nicolasdeloof582/bidule@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1
  Digest:                                        sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1
  MediaType:                                     application/vnd.oci.image.index.v1+json
  Annotations:                                   
    containerd.io/distribution.source.docker.io: library/alpine

# 4bcff639.. is actually alpine/latest, mounted in compose artifact repository
#

Related issue
see #13238
see https://github.com/docker-archive-public/docker.app

(not mandatory) A picture of a cute animal, if possible in relation to what you did
image

@ndeloof ndeloof requested a review from a team as a code owner October 1, 2025 07:17
@ndeloof ndeloof requested a review from glours October 1, 2025 07:17
@ndeloof ndeloof marked this pull request as draft October 1, 2025 07:26
@ndeloof ndeloof force-pushed the bundle branch 8 times, most recently from 828a5f7 to 208ec3a Compare October 1, 2025 15:20
@ndeloof ndeloof marked this pull request as ready for review October 3, 2025 07:01
Copy link
Contributor

@glours glours left a comment

Choose a reason for hiding this comment

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

LGTM + tests ok 👌

@ndeloof ndeloof merged commit 07602f2 into docker:main Oct 3, 2025
70 of 72 checks passed
@ndeloof ndeloof deleted the bundle branch October 3, 2025 09:00
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Oct 10, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [docker/compose](https://github.com/docker/compose) | minor | `v2.39.4` -> `v2.40.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>docker/compose (docker/compose)</summary>

### [`v2.40.0`](https://github.com/docker/compose/releases/tag/v2.40.0)

[Compare Source](docker/compose@v2.39.4...v2.40.0)

#### What's Changed

##### ✨ Improvements

- publish Compose application as compose.yaml + images by [@&#8203;ndeloof](https://github.com/ndeloof) in [#&#8203;13257](docker/compose#13257)

##### 🐛 Fixes

- resolve secrets based on env var before executing bake by [@&#8203;ndeloof](https://github.com/ndeloof) in [#&#8203;13237](docker/compose#13237)
- pass bake secrets by env by [@&#8203;ndeloof](https://github.com/ndeloof) in [#&#8203;13249](docker/compose#13249)
- escape $ in bake.json as interpolation already has been managed by cpmpose by [@&#8203;ndeloof](https://github.com/ndeloof) in [#&#8203;13259](docker/compose#13259)

##### 🔧  Internal

- pkg/compose: remove uses of deprecated mitchellh/mapstructure module by [@&#8203;thaJeztah](https://github.com/thaJeztah) in [#&#8203;13239](docker/compose#13239)
- pkg/watch: remove unused IsWindowsShortReadError by [@&#8203;thaJeztah](https://github.com/thaJeztah) in [#&#8203;13052](docker/compose#13052)
- pkg/compose: build: remove permissions warning on Windows by [@&#8203;thaJeztah](https://github.com/thaJeztah) in [#&#8203;13236](docker/compose#13236)
- pluginMain: remove uses of DockerCLI.Apply by [@&#8203;thaJeztah](https://github.com/thaJeztah) in [#&#8203;13240](docker/compose#13240)
- use containerd registry client by [@&#8203;ndeloof](https://github.com/ndeloof) in [#&#8203;13245](docker/compose#13245)
- provider services: use '--project-name=' notation by [@&#8203;glours](https://github.com/glours) in [#&#8203;13250](docker/compose#13250)
- gha: update test-matrix: remove docker 26.x by [@&#8203;thaJeztah](https://github.com/thaJeztah) in [#&#8203;13254](docker/compose#13254)
- pkg/compose: explicitly map AuthConfig fields instead of a direct cast by [@&#8203;thaJeztah](https://github.com/thaJeztah) in [#&#8203;13253](docker/compose#13253)
- cmd/compose: fix minor linting issues by [@&#8203;thaJeztah](https://github.com/thaJeztah) in [#&#8203;13252](docker/compose#13252)
- use containerd client for OCI operations by [@&#8203;ndeloof](https://github.com/ndeloof) in [#&#8203;13251](docker/compose#13251)

##### ⚙️ Dependencies

- build(deps): bump github.com/docker/docker, docker/cli v28.5.0-rc.1 by [@&#8203;thaJeztah](https://github.com/thaJeztah) in [#&#8203;13241](docker/compose#13241)
- build(deps): bump github.com/docker/docker from 28.5.0-rc.1+incompatible to 28.5.0+incompatible by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;13260](docker/compose#13260)
- build(deps): bump github.com/docker/cli from 28.5.0-rc.1+incompatible to 28.5.0+incompatible by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;13261](docker/compose#13261)

**Full Changelog**: <docker/compose@v2.39.4...v2.40.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzIuNSIsInVwZGF0ZWRJblZlciI6IjQxLjEzMi41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
@Silvanoc
Copy link

Silvanoc commented Oct 11, 2025

@ndeloof I have some comments on the design of the OCI artifact:

  1. For the time being I would avoid the use of Subject as only mechanism to define the relationship. The API required to query which manifests refer the subject and therefore depend on its existence (the referrers API) is not supported yet by widely used container registries like those of GitHub and GitLab.
  2. I personally would rather try to use so-called "nested indexes", because they are much better supported that Subject. Although I have to admit that I don't have a clear idea on how to structure it yet.
  3. If using Subject, the inverse relationship should be used. The way you've defined it, you're forcing exiting container image indexes/manifests to be modified in order to add the Subject. It is the docker-compose document the one establishing the relationship and not the container images.

In general, the lifecycle of a manifest providing a Subject depends on the lifecycle of the referred manifests. But not the way around. And it is the compose that depends on the existence of the images and not the other way around. You can create and destroy compose configurations without needing any changes to the images.

@ndeloof
Copy link
Contributor Author

ndeloof commented Oct 12, 2025

My initial implementation was relying on publishing an image index, the OCI artifact being one of the entries and service images the many others. This is the approach we adopted for https://github.com/docker-archive-public/docker.app by the time
This comes with a few drawbacks:

  • the OCI artifact is "hidden" as an entry in the index list, and as such we loose web UI integration on Docker Hub to give user guidance on how to use
  • this requires the consuming code to be updated, which means older version of Compose would not be able to use compose application published by a recent release

Use of Subject made a balanced solution, with backward compatibility and benefits to get registry aware of OCI artifact relation with images. For sure, this require registry to support this, and some don't (yet) support this - but I guess they will mid-terms as this is the basis for secure supply chain (see https://learn.microsoft.com/en-us/azure/container-registry/container-registry-manage-artifact for illustration)

If using Subject, the inverse relationship should be used. The way you've defined it, you're forcing exiting container image indexes/manifests to be modified in order to add the Subject. It is the docker-compose document the one establishing the relationship and not the container images.

the artifact being published is an index list, will all services images. This group only exists because it is used by a Compose application. So the lifecycle of this manifest depends on the referred manifest: if compose application is updated, index list will probably be as well (until images aren't updated)

@Silvanoc
Copy link

Silvanoc commented Nov 5, 2025

I'm not convinced that this OCI artifact structure is the best one I can think of. I've created therefore #13354 to sketch my ideas.

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.

3 participants