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

image save: make output tarball OCI compliant #44598

Merged
merged 2 commits into from Jun 9, 2023

Conversation

cpuguy83
Copy link
Member

@cpuguy83 cpuguy83 commented Dec 7, 2022

  • Moves blobs for the tarball into the OCI compliant paths (blobs/<alg>/<digest>)
  • Removes old VERSION file which has no meaning and can't be used anyway in the new format
  • Adds oci-layout, oci manifest, and index files to the outputted tars

For the new files this just goes ahead and uses OCI media types (instead of old docker types) since these are new and should not break anything.

All this works because the old docker layout is dependent on the manifest.json file at the root of the tar which has paths to each of the blobs in the tarball. The change updates the paths in the manifest to point to the new paths.

This is the same technique used by buildkit to support both OCI tar formats as well as legacy docker ones.

@thaJeztah
Copy link
Member

Looks like there's some tests to adjust (or perhaps separate tests)

=== FAIL: amd64.integration-cli TestDockerCLISaveLoadSuite/TestSaveCheckTimes (0.04s)
    docker_cli_save_load_test.go:127: assertion failed: error is not nil: exit status 1: failed to save repo with image ID and 'repositories' file: , exit status 1
    --- FAIL: TestDockerCLISaveLoadSuite/TestSaveCheckTimes (0.04s)

=== FAIL: amd64.integration-cli TestDockerCLISaveLoadSuite/TestSaveDirectoryPermissions (0.79s)
    docker_cli_save_load_test.go:302: assertion failed: error is not nil: open /tmp/save-layers-with-directories3203220919/image-extraction-dir/blobs/layer.tar: no such file or directory: failed to open /tmp/save-layers-with-directories3203220919/image-extraction-dir/blobs/layer.tar: open /tmp/save-layers-with-directories3203220919/image-extraction-dir/blobs/layer.tar: no such file or directory
    --- FAIL: TestDockerCLISaveLoadSuite/TestSaveDirectoryPermissions (0.79s)

=== FAIL: amd64.integration-cli TestDockerCLISaveLoadSuite/TestSaveRepoWithMultipleImages (0.84s)
    docker_cli_save_load_test.go:266: assertion failed: 
        --- actual
        +++ expected
          []string(
        - 	nil,
        + 	{
        + 		"1c35c441208254cb7c3844ba95a96485388cef9ccc0646d562c7fc026e04c807",
        + 		"af4544b16613a2573c47ad04472359062ae9a0968bd5cfb9fe271861df9fe286",
        + 		"c4305557e19f493d6f6eec7a544c2ae248ab17528a8b34fe9339cba8d70059e4",
        + 	},
          )
        : archive does not contains the right layers: got [], expected [1c35c441208254cb7c3844ba95a96485388cef9ccc0646d562c7fc026e04c807 af4544b16613a2573c47ad04472359062ae9a0968bd5cfb9fe271861df9fe286 c4305557e19f493d6f6eec7a544c2ae248ab17528a8b34fe9339cba8d70059e4], output: "sha256:1c35c441208254cb7c3844ba95a96485388cef9ccc0646d562c7fc026e04c807"
    --- FAIL: TestDockerCLISaveLoadSuite/TestSaveRepoWithMultipleImages (0.84s)


ociIndexFileName = "index.json"
ociLayoutFilename = "oci-layout"
ociLayoutContent = `{"imageLayoutVersion": "1.0.0"}`
)

Copy link
Member

Choose a reason for hiding this comment

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

Can we just use https://github.com/containerd/containerd/blob/main/images/archive/exporter.go ?
For containerd-integration mode.

Copy link
Member Author

Choose a reason for hiding this comment

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

I believe that's the plan.

Copy link
Member

@tianon tianon left a comment

Choose a reason for hiding this comment

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

Generally looks OK to me! I made a couple minor comments, but I don't think it's anything very serious. I'm both looking forward to having/using this and to this code going away with the containerd integration. 😄

image/tarexport/save.go Outdated Show resolved Hide resolved
image/tarexport/save.go Show resolved Hide resolved
image/tarexport/save.go Outdated Show resolved Hide resolved
This moves the blobs around so they follow the OCI spec.
Note that because docker reads paths from the manifest.json inside the
tar this is not a breaking change.

This does, however, remove the old layer "VERSION" file which had a big
"why is this even here" in the code comments. I suspect it does not
matter at all even for really old versions of Docker. In any case it is
a useless file for any even relatively modern version of Docker.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
@cpuguy83 cpuguy83 force-pushed the save_tar_oci branch 4 times, most recently from f8f7e23 to 8c5db61 Compare May 24, 2023 01:16
@@ -108,25 +99,6 @@ func (s *DockerCLISaveLoadSuite) TestSaveSingleTag(c *testing.T) {
assert.NilError(c, err, "failed to save repo with image ID and 'repositories' file: %s, %v", out, err)
}

func (s *DockerCLISaveLoadSuite) TestSaveCheckTimes(c *testing.T) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Note, these tests were incorrectly poking at the saved tarball (assuming a file location instead of looking at the manifest).
I had to do major surgery on these so I just moved them over to integration/.

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

Went through some of the changes (but perhaps need to take another look later); left some comments / suggestions / questions inline, but overall looking 👍

integration/image/save_test.go Show resolved Hide resolved
f, err := tarfs.Open(p)
assert.NilError(t, err)

entries, err := listTar(f)
Copy link
Member

Choose a reason for hiding this comment

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

Wondering if this listTar could (not for this PR) also handled by your tar2go (fs.Glob(tarfs, "dev/*") and/or fs.WalkDir(tarfs)) 🤩

image/tarexport/save.go Outdated Show resolved Hide resolved
image/image.go Outdated Show resolved Hide resolved
image/image.go Outdated Show resolved Hide resolved
image/tarexport/save.go Outdated Show resolved Hide resolved
image/tarexport/save.go Outdated Show resolved Hide resolved
image/tarexport/save.go Outdated Show resolved Hide resolved
image/tarexport/save.go Outdated Show resolved Hide resolved
This makes the output of `docker save` fully OCI compliant.

When using the containerd image store, this code is not used. That
exporter will just use containerd's export method and should give us the
output we want for multi-arch images.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
@cpuguy83
Copy link
Member Author

This is all updated.

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

LGTM

@thaJeztah thaJeztah added this to the 25.0.0 milestone Jun 9, 2023
@thaJeztah thaJeztah merged commit f139017 into moby:master Jun 9, 2023
101 checks passed
@cpuguy83 cpuguy83 deleted the save_tar_oci branch June 29, 2023 19:16
Size: int64(len(imageDescr.image.RawJSON())),
Platform: &imgPlat,
},
Layers: foreign,
Copy link
Member

Choose a reason for hiding this comment

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

Non-foreign layers were accidentally dropped?

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

Successfully merging this pull request may close these issues.

None yet

5 participants