Repository: moby/moby
Pull request #49815: docs/api: update image tarball format
Author: login: z63d
Labels: name: status/3-docs-review
name: area/docs
name: area/images
description: Image Service
Created: 2025-04-16T02:58:02Z | Merged: 2025-04-16T11:05:22Z

**- What I did**

fixes https://github.com/moby/moby/issues/48967

**- How I did it**

**- How to verify it**

**- Human readable description for the release notes**
<!--
Write a short (one line) summary that describes the changes in this
pull request for inclusion in the changelog.
It must be placed inside the below triple backticks section.

NOTE: Only fill this section if changes introduced in this PR are user-facing.
The PR must have a relevant impact/ label.
-->
```markdown changelog

```

**- A picture of a cute animal (not mandatory but encouraged)**




Diff:
diff --git a/api/swagger.yaml b/api/swagger.yaml
index 9d75e98d2751e..1183aaf2b59d6 100644
--- a/api/swagger.yaml
+++ b/api/swagger.yaml
@@ -10491,13 +10491,9 @@ paths:
 
         ### Image tarball format
 
-        An image tarball contains one directory per image layer (named using its long ID), each containing these files:
+        An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md#content).
 
-        - `VERSION`: currently `1.0` - the file format version
-        - `json`: detailed layer information, similar to `docker inspect layer_id`
-        - `layer.tar`: A tarfile containing the filesystem changes in this layer
-
-        The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
+        Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
 
         If the tarball defines a repository, the tarball should also include a `repositories` file at the root that contains a list of repository and tag names mapped to layer IDs.
 
diff --git a/docs/api/v1.44.yaml b/docs/api/v1.44.yaml
index 0ef23a392e773..8e4e6121e622a 100644
--- a/docs/api/v1.44.yaml
+++ b/docs/api/v1.44.yaml
@@ -9647,13 +9647,9 @@ paths:
 
         ### Image tarball format
 
-        An image tarball contains one directory per image layer (named using its long ID), each containing these files:
+        An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md#content).
 
-        - `VERSION`: currently `1.0` - the file format version
-        - `json`: detailed layer information, similar to `docker inspect layer_id`
-        - `layer.tar`: A tarfile containing the filesystem changes in this layer
-
-        The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
+        Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
 
         If the tarball defines a repository, the tarball should also include a `repositories` file at the root that contains a list of repository and tag names mapped to layer IDs.
 
diff --git a/docs/api/v1.45.yaml b/docs/api/v1.45.yaml
index e0ec5013cc5ac..56d346fea4ce9 100644
--- a/docs/api/v1.45.yaml
+++ b/docs/api/v1.45.yaml
@@ -9627,13 +9627,9 @@ paths:
 
         ### Image tarball format
 
-        An image tarball contains one directory per image layer (named using its long ID), each containing these files:
+        An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md#content).
 
-        - `VERSION`: currently `1.0` - the file format version
-        - `json`: detailed layer information, similar to `docker inspect layer_id`
-        - `layer.tar`: A tarfile containing the filesystem changes in this layer
-
-        The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
+        Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
 
         If the tarball defines a repository, the tarball should also include a `repositories` file at the root that contains a list of repository and tag names mapped to layer IDs.
 
diff --git a/docs/api/v1.46.yaml b/docs/api/v1.46.yaml
index b6ff826e7a967..8c4be6c3ce017 100644
--- a/docs/api/v1.46.yaml
+++ b/docs/api/v1.46.yaml
@@ -9761,13 +9761,9 @@ paths:
 
         ### Image tarball format
 
-        An image tarball contains one directory per image layer (named using its long ID), each containing these files:
+        An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md#content).
 
-        - `VERSION`: currently `1.0` - the file format version
-        - `json`: detailed layer information, similar to `docker inspect layer_id`
-        - `layer.tar`: A tarfile containing the filesystem changes in this layer
-
-        The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
+        Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
 
         If the tarball defines a repository, the tarball should also include a `repositories` file at the root that contains a list of repository and tag names mapped to layer IDs.
 
diff --git a/docs/api/v1.47.yaml b/docs/api/v1.47.yaml
index e5e76c1bc5903..4eb222a050743 100644
--- a/docs/api/v1.47.yaml
+++ b/docs/api/v1.47.yaml
@@ -9902,13 +9902,9 @@ paths:
 
         ### Image tarball format
 
-        An image tarball contains one directory per image layer (named using its long ID), each containing these files:
+        An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md#content).
 
-        - `VERSION`: currently `1.0` - the file format version
-        - `json`: detailed layer information, similar to `docker inspect layer_id`
-        - `layer.tar`: A tarfile containing the filesystem changes in this layer
-
-        The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
+        Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
 
         If the tarball defines a repository, the tarball should also include a `repositories` file at the root that contains a list of repository and tag names mapped to layer IDs.
 
diff --git a/docs/api/v1.48.yaml b/docs/api/v1.48.yaml
index 660e81e16eacc..a2901377e5b59 100644
--- a/docs/api/v1.48.yaml
+++ b/docs/api/v1.48.yaml
@@ -10491,13 +10491,9 @@ paths:
 
         ### Image tarball format
 
-        An image tarball contains one directory per image layer (named using its long ID), each containing these files:
+        An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md#content).
 
-        - `VERSION`: currently `1.0` - the file format version
-        - `json`: detailed layer information, similar to `docker inspect layer_id`
-        - `layer.tar`: A tarfile containing the filesystem changes in this layer
-
-        The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
+        Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
 
         If the tarball defines a repository, the tarball should also include a `repositories` file at the root that contains a list of repository and tag names mapped to layer IDs.
 
diff --git a/docs/api/v1.49.yaml b/docs/api/v1.49.yaml
index 9d75e98d2751e..1183aaf2b59d6 100644
--- a/docs/api/v1.49.yaml
+++ b/docs/api/v1.49.yaml
@@ -10491,13 +10491,9 @@ paths:
 
         ### Image tarball format
 
-        An image tarball contains one directory per image layer (named using its long ID), each containing these files:
+        An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md#content).
 
-        - `VERSION`: currently `1.0` - the file format version
-        - `json`: detailed layer information, similar to `docker inspect layer_id`
-        - `layer.tar`: A tarfile containing the filesystem changes in this layer
-
-        The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
+        Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
 
         If the tarball defines a repository, the tarball should also include a `repositories` file at the root that contains a list of repository and tag names mapped to layer IDs.
 


Reviews:
user: login: thaJeztah
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-16T08:35:11Z
user: login: thaJeztah
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-16T08:35:53Z
user: login: vvoland
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-16T10:04:04Z
user: login: vvoland
body: For context - OCI-compatible `docker save` output was introduced in https://github.com/moby/moby/pull/44598 which was a part of the 25.0.0 release with API v1.44.


LGTM; thanks!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-16T10:10:43Z
user: login: thaJeztah
body: LGTM, thanks!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-16T11:04:40Z

Review comments:
diff_hunk: @@ -10491,13 +10491,9 @@ paths:
 
         ### Image tarball format
 
-        An image tarball contains one directory per image layer (named using its long ID), each containing these files:
+        An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/main/image-layout.md#content).
path: api/swagger.yaml
user: login: thaJeztah
body: It's probably good to use a perma-link for this, in case the URL or anchor changes; we could use the latest tag for now (`v1.1.1`); `https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md#content`
created_at: 2025-04-16T08:13:13Z
author_association: MEMBER
diff_hunk: @@ -10491,13 +10491,9 @@ paths:
 
         ### Image tarball format
 
-        An image tarball contains one directory per image layer (named using its long ID), each containing these files:
+        An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/main/image-layout.md#content).
 
-        - `VERSION`: currently `1.0` - the file format version
-        - `json`: detailed layer information, similar to `docker inspect layer_id`
-        - `layer.tar`: A tarfile containing the filesystem changes in this layer
-
-        The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
+        Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
path: api/swagger.yaml
user: login: thaJeztah
body: I did a quick check, and there's also a `repositories` file in the output; I'm not sure now if that one is part of the OCI spec (I don't see it mentioned at a glance), or it that was for backward compatibility as well 🤔 (maybe someone else remembers); 


On a Docker 28.0.4 engine; (new, OCI "hybrid" layout);

```bash
docker save alpine:latest | tar -t
blobs/
blobs/sha256/
blobs/sha256/8d591b0b7dea080ea3be9e12ae563eebf9869168ffced1cb25b2470a3d9fe15e
blobs/sha256/971b11a1db2fd5afa66b9aebe64725d29e68780c3ed4596dcf2412e374423573
blobs/sha256/a16e98724c05975ee8c40d8fe389c3481373d34ab20a1cf52ea2accc43f71f4c
blobs/sha256/ac7c8a62db68f97f3d3cb6d5a833137a81f12820a9af0055c1fed789fae110f0
index.json
manifest.json
oci-layout
repositories
```

_However_ that file is not present when using the containerd image store, so I suspect it was part of the legacy format;

On Docker 28.0.4 with the containerd snapshotter enabled;


```bash
docker save alpine:latest | tar -t
blobs/
blobs/sha256/
blobs/sha256/6e771e15690e2fabf2332d3a3b744495411d6e0b00b2aea64419b58b0066cf81
blobs/sha256/757d680068d77be46fd1ea20fb21db16f150468c5e7079a08a2e4705aec096ac
blobs/sha256/8d591b0b7dea080ea3be9e12ae563eebf9869168ffced1cb25b2470a3d9fe15e
blobs/sha256/a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c
index.json
manifest.json
oci-layout
```
```bash
docker save -o alpine.tar alpine:latest
mkdir temp
cd temp
tar -xvf alpine

cat repositories
{"alpine":{"latest":"a16e98724c05975ee8c40d8fe389c3481373d34ab20a1cf52ea2accc43f71f4c"}}
```


On a Docker 23.0.4 engine (old layout);

```bash
docker save alpine:latest | tar -t
193e8f721996a3f15b53e3fc5c0abb059338a5607454eb6f7cc63c56e6494ab1/
193e8f721996a3f15b53e3fc5c0abb059338a5607454eb6f7cc63c56e6494ab1/VERSION
193e8f721996a3f15b53e3fc5c0abb059338a5607454eb6f7cc63c56e6494ab1/json
193e8f721996a3f15b53e3fc5c0abb059338a5607454eb6f7cc63c56e6494ab1/layer.tar
91ef0af61f39ece4d6710e465df5ed6ca12112358344fd51ae6a3b886634148b.json
manifest.json
repositories
```



created_at: 2025-04-16T08:35:04Z
author_association: MEMBER
diff_hunk: @@ -10491,13 +10491,9 @@ paths:
 
         ### Image tarball format
 
-        An image tarball contains one directory per image layer (named using its long ID), each containing these files:
+        An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/main/image-layout.md#content).
 
-        - `VERSION`: currently `1.0` - the file format version
-        - `json`: detailed layer information, similar to `docker inspect layer_id`
-        - `layer.tar`: A tarfile containing the filesystem changes in this layer
-
-        The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
+        Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
path: api/swagger.yaml
user: login: thaJeztah
body: @vvoland do you recall perhaps? (i.e. was the `repositories` file intentionally removed with the containerd image-store enabled, or was this something still left to implement?
created_at: 2025-04-16T08:35:52Z
author_association: MEMBER
diff_hunk: @@ -10491,13 +10491,9 @@ paths:
 
         ### Image tarball format
 
-        An image tarball contains one directory per image layer (named using its long ID), each containing these files:
+        An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/main/image-layout.md#content).
 
-        - `VERSION`: currently `1.0` - the file format version
-        - `json`: detailed layer information, similar to `docker inspect layer_id`
-        - `layer.tar`: A tarfile containing the filesystem changes in this layer
-
-        The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
+        Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
path: api/swagger.yaml
user: login: vvoland
body: `repositories` is not a part of OCI - it's a part of the Docker Image Spec v1.0 - https://github.com/moby/docker-image-spec/blob/v1.1.0/v1.md


However, both v1.1 and v1.2 now use `manifest.json` and keep the `repositories` only for backwards compatibility with implementations that only understand Docker Image v1.0.

It's not generated by the containerd archive save and we didn't go out of our way to re-implement it.


created_at: 2025-04-16T10:04:03Z
author_association: CONTRIBUTOR

PR comments:
user: login: thaJeztah
created_at: 2025-04-16T08:57:20Z
body: Oh! If you're updating; could you update your DCO sign-off to use your real name ("Kaita Nakamura" if that's the correct name) https://github.com/moby/moby/blob/master/CONTRIBUTING.md#sign-your-work

You may need to [adjust your git config](https://github.com/moby/moby/blob/master/docs/contributing/set-up-git.md#task-2-set-your-signature-and-an-upstream-remote) (`git config --global  user.name "FirstName LastName"` (or `--local`, depending)) to match that (for the DCO check to be happy, as it compares the commit author with the sign-off).

<img width="532" alt="Screenshot 2025-04-16 at 10 52 23" src="https://github.com/user-attachments/assets/44c2ce1b-fc81-43fc-a852-84a6c4293600" />




author_association: MEMBER
user: login: thaJeztah
created_at: 2025-04-16T11:05:10Z
body: Failure on Windows is unrelated; 

```
=== Failed
=== FAIL: github.com/docker/docker/integration/container TestWaitNonBlocked/wait-nonblocking-exit-random (60.35s)
    wait_test.go:44: assertion failed: error is not nil: error during connect: Post "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.49/containers/create": EOF
```
author_association: MEMBER