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

Refactor meta.jq to prepare for signing and oci-import implementation #17

Merged
merged 1 commit into from
Jan 26, 2024

Conversation

tianon
Copy link
Member

@tianon tianon commented Jan 25, 2024

  • explicit "containerd image storage in dockerd" placeholder
  • explicit "annotations" helper/generator (so they can be added in the oci-import builder later)
  • setting the org.opencontainers.image.created annoation inside the image index to the actual build date (otherwise SOURCE_DATE_EPOCH makes it hard to tell an image is actually freshly built)
  • more whitespace in generated commands for better readability
  • extract OCI tar in the build step (so the "output" of the build is an OCI layout directory vs tarball) instead of the pull step (so we can more ergonomically add pre-push signing)
  • use buildx's --annotation flag for making annotations easier to read

@tianon
Copy link
Member Author

tianon commented Jan 25, 2024

An example generated build command:

# jq -L .scripts 'include "meta"; first(.[]) | build_command' -r ../builds.json
SOURCE_DATE_EPOCH=1705382289 \
	docker buildx build --progress=plain \
	--provenance=mode=max \
	--output '"type=oci","dest=temp.tar"' \
	--annotation 'org.opencontainers.image.source=https://github.com/tianon/docker-bash.git#b08b986ade4dab726334b111c89688491534b732:devel' \
	--annotation 'org.opencontainers.image.revision=b08b986ade4dab726334b111c89688491534b732' \
	--annotation 'org.opencontainers.image.created=2024-01-16T05:18:09Z' \
	--annotation 'org.opencontainers.image.version=devel-20240114' \
	--annotation 'org.opencontainers.image.url=https://hub.docker.com/_/bash' \
	--annotation 'manifest-descriptor:org.opencontainers.image.source=https://github.com/tianon/docker-bash.git#b08b986ade4dab726334b111c89688491534b732:devel' \
	--annotation 'manifest-descriptor:org.opencontainers.image.revision=b08b986ade4dab726334b111c89688491534b732' \
	--annotation 'manifest-descriptor:org.opencontainers.image.created=2024-01-25T22:46:52Z' \
	--annotation 'manifest-descriptor:org.opencontainers.image.version=devel-20240114' \
	--annotation 'manifest-descriptor:org.opencontainers.image.url=https://hub.docker.com/_/bash' \
	--tag 'bash:devel-20240114' \
	--tag 'bash:devel' \
	--tag 'bash:devel-20240114-alpine3.19' \
	--tag 'bash:devel-alpine3.19' \
	--tag 'amd64/bash:devel-20240114' \
	--tag 'amd64/bash:devel' \
	--tag 'amd64/bash:devel-20240114-alpine3.19' \
	--tag 'amd64/bash:devel-alpine3.19' \
	--tag 'oisupport/staging-amd64:dbfd320b24fdbcf3e17174640287049bde81906f59592b6d4e3e42f47f9b5517' \
	--platform 'linux/amd64' \
	--build-context 'alpine:3.19=docker-image://alpine:3.19@sha256:13b7e62e8df80264dbb747995705a986aa530415763a6c58f84a3ca8af9a5bcd' \
	--build-arg BUILDKIT_SYNTAX="$BASHBREW_BUILDKIT_SYNTAX" \
	--file 'Dockerfile' \
	'https://github.com/tianon/docker-bash.git#b08b986ade4dab726334b111c89688491534b732:devel'
mkdir temp
tar -xvf temp.tar -C temp
rm temp.tar
jq '
	.manifests |= (
		del(.[].annotations)
		| unique
		| if length != 1 then
			error("unexpected number of manifests: " + length)
		else . end
	)
' temp/index.json > temp/index.json.new
mv temp/index.json.new temp/index.json

@tianon
Copy link
Member Author

tianon commented Jan 25, 2024

Realizing we could (ab)use our sources.json and builds.json test suite to generate some example commands in the repo itself so that changes like this actually show what the pull/build/push command change is (and helps illustrate why the changes are being made). 👀

So, feel free to review this, but I think I'm going to work on that as a separate thing so I can use this PR as the guinea pig for showing off the result of it.

@tianon
Copy link
Member Author

tianon commented Jan 25, 2024

Rebased on top of #18 so the diff to .test/example-commands.sh is more interesting/useful. 👀

…tion

- explicit "containerd image storage in dockerd" placeholder
- explicit "annotations" helper/generator (so they can be added in the `oci-import` builder later)
- setting the `org.opencontainers.image.created` annoation inside the image index to the actual build date (otherwise `SOURCE_DATE_EPOCH` makes it hard to tell an image is actually freshly built)
- more whitespace in generated commands for better readability
- extract OCI tar in the build step (so the "output" of the build is an OCI layout directory vs tarball) instead of the pull step (so we can more ergonomically add pre-push signing)
- use buildx's `--annotation` flag for making annotations easier to read
@@ -3,15 +3,49 @@

# </pull>
# <build>
SOURCE_DATE_EPOCH=1700741054 docker buildx build --progress=plain --provenance=mode=max --sbom=generator="$BASHBREW_BUILDKIT_SBOM_GENERATOR" --output '"type=oci","dest=temp.tar","annotation.org.opencontainers.image.source=https://github.com/docker-library/docker.git#6d541d27b5dd12639e5a33a675ebca04d3837d74:24/cli","annotation-manifest-descriptor.org.opencontainers.image.source=https://github.com/docker-library/docker.git#6d541d27b5dd12639e5a33a675ebca04d3837d74:24/cli","annotation.org.opencontainers.image.revision=6d541d27b5dd12639e5a33a675ebca04d3837d74","annotation-manifest-descriptor.org.opencontainers.image.revision=6d541d27b5dd12639e5a33a675ebca04d3837d74","annotation.org.opencontainers.image.version=24.0.7-cli","annotation-manifest-descriptor.org.opencontainers.image.version=24.0.7-cli","annotation.org.opencontainers.image.url=https://hub.docker.com/_/docker","annotation-manifest-descriptor.org.opencontainers.image.url=https://hub.docker.com/_/docker"' --tag 'docker:24.0.7-cli' --tag 'docker:24.0-cli' --tag 'docker:24-cli' --tag 'docker:cli' --tag 'docker:24.0.7-cli-alpine3.18' --tag 'oisupport/staging-amd64:4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43' --platform 'linux/amd64' --build-context 'alpine:3.18=docker-image://alpine:3.18@sha256:d695c3de6fcd8cfe3a6222b0358425d40adfd129a8a47c3416faff1a8aece389' --build-arg BUILDKIT_SYNTAX="$BASHBREW_BUILDKIT_SYNTAX" --file 'Dockerfile' 'https://github.com/docker-library/docker.git#6d541d27b5dd12639e5a33a675ebca04d3837d74:24/cli'
Copy link
Member Author

Choose a reason for hiding this comment

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

This change is much cuter with --ignore-all-space --word-diff:

Diff:

image

diff --git a/.test/example-commands.sh b/.test/example-commands.sh
index f165244..4bcbaf8 100644
--- a/.test/example-commands.sh
+++ b/.test/example-commands.sh
@@ -3,15 +3,49 @@

# </pull>
# <build>
SOURCE_DATE_EPOCH=1700741054 {+\+}
	docker buildx build --progress=plain {+\+}
	--provenance=mode=max {+\+}
	--sbom=generator="$BASHBREW_BUILDKIT_SBOM_GENERATOR" {+\+}
	--output [-'"type=oci","dest=temp.tar","annotation.org.opencontainers.image.source=https://github.com/docker-library/docker.git#6d541d27b5dd12639e5a33a675ebca04d3837d74:24/cli","annotation-manifest-descriptor.org.opencontainers.image.source=https://github.com/docker-library/docker.git#6d541d27b5dd12639e5a33a675ebca04d3837d74:24/cli","annotation.org.opencontainers.image.revision=6d541d27b5dd12639e5a33a675ebca04d3837d74","annotation-manifest-descriptor.org.opencontainers.image.revision=6d541d27b5dd12639e5a33a675ebca04d3837d74","annotation.org.opencontainers.image.version=24.0.7-cli","annotation-manifest-descriptor.org.opencontainers.image.version=24.0.7-cli","annotation.org.opencontainers.image.url=https://hub.docker.com/_/docker","annotation-manifest-descriptor.org.opencontainers.image.url=https://hub.docker.com/_/docker"'-]{+'"type=oci","dest=temp.tar"' \+}
{+	--annotation 'org.opencontainers.image.source=https://github.com/docker-library/docker.git#6d541d27b5dd12639e5a33a675ebca04d3837d74:24/cli' \+}
{+	--annotation 'org.opencontainers.image.revision=6d541d27b5dd12639e5a33a675ebca04d3837d74' \+}
{+	--annotation 'org.opencontainers.image.created=2023-11-23T12:04:14Z' \+}
{+	--annotation 'org.opencontainers.image.version=24.0.7-cli' \+}
{+	--annotation 'org.opencontainers.image.url=https://hub.docker.com/_/docker' \+}
{+	--annotation 'manifest-descriptor:org.opencontainers.image.source=https://github.com/docker-library/docker.git#6d541d27b5dd12639e5a33a675ebca04d3837d74:24/cli' \+}
{+	--annotation 'manifest-descriptor:org.opencontainers.image.revision=6d541d27b5dd12639e5a33a675ebca04d3837d74' \+}
{+	--annotation 'manifest-descriptor:org.opencontainers.image.created=1970-01-01T00:00:00Z' \+}
{+	--annotation 'manifest-descriptor:org.opencontainers.image.version=24.0.7-cli' \+}
{+	--annotation 'manifest-descriptor:org.opencontainers.image.url=https://hub.docker.com/_/docker' \+}
	--tag 'docker:24.0.7-cli' {+\+}
	--tag 'docker:24.0-cli' {+\+}
	--tag 'docker:24-cli' {+\+}
	--tag 'docker:cli' {+\+}
	--tag 'docker:24.0.7-cli-alpine3.18' {+\+}
	--tag 'oisupport/staging-amd64:4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43' {+\+}
	--platform 'linux/amd64' {+\+}
	--build-context 'alpine:3.18=docker-image://alpine:3.18@sha256:d695c3de6fcd8cfe3a6222b0358425d40adfd129a8a47c3416faff1a8aece389' {+\+}
	--build-arg BUILDKIT_SYNTAX="$BASHBREW_BUILDKIT_SYNTAX" {+\+}
	--file 'Dockerfile' {+\+}
	'https://github.com/docker-library/docker.git#6d541d27b5dd12639e5a33a675ebca04d3837d74:24/cli'[-# </build>-]
[-# <push>-]
mkdir temp
tar -xvf temp.tar -C temp
{+rm temp.tar+}
jq [-'.manifests-]{+'+}
{+	.manifests+} |= [-(del(.[].annotations)-]{+(+}
{+		del(.[].annotations)+}
		| [-unique)'-]{+unique+}
{+		| if length != 1 then+}
{+			error("unexpected number of manifests: " + length)+}
{+		else . end+}
{+	)+}
{+'+} temp/index.json > temp/index.json.new
mv temp/index.json.new temp/index.json
{+# </build>+}
{+# <push>+}
crane push temp 'oisupport/staging-amd64:4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43'
rm -rf temp[-temp.tar-]
# </push>

# docker:24.0.7-windowsservercore-ltsc2022 [windows-amd64]
@@ -20,7 +54,21 @@ docker pull 'mcr.microsoft.com/windows/servercore:ltsc2022@sha256:d4ab2dd7d3d0fc
docker tag 'mcr.microsoft.com/windows/servercore:ltsc2022@sha256:d4ab2dd7d3d0fce6edc5df459565a4c96bbb1d0148065b215ab5ddcab1e42eb4' 'mcr.microsoft.com/windows/servercore:ltsc2022'
# </pull>
# <build>
SOURCE_DATE_EPOCH=1700741054 {+\+}
	DOCKER_BUILDKIT=0 {+\+}
	docker build {+\+}
	--tag 'docker:24.0.7-windowsservercore-ltsc2022' {+\+}
	--tag 'docker:24.0-windowsservercore-ltsc2022' {+\+}
	--tag 'docker:24-windowsservercore-ltsc2022' {+\+}
	--tag 'docker:windowsservercore-ltsc2022' {+\+}
	--tag 'docker:24.0.7-windowsservercore' {+\+}
	--tag 'docker:24.0-windowsservercore' {+\+}
	--tag 'docker:24-windowsservercore' {+\+}
	--tag 'docker:windowsservercore' {+\+}
	--tag 'oisupport/staging-windows-amd64:9b405cfa5b88ba65121aabdb95ae90fd2e1fee7582174de82ae861613ae3072e' {+\+}
	--platform 'windows/amd64' {+\+}
	--file 'Dockerfile' {+\+}
	'https://github.com/docker-library/docker.git#6d541d27b5dd12639e5a33a675ebca04d3837d74:24/windows/windowsservercore-ltsc2022'
# </build>
# <push>
docker push 'oisupport/staging-windows-amd64:9b405cfa5b88ba65121aabdb95ae90fd2e1fee7582174de82ae861613ae3072e'

@yosifkit yosifkit merged commit a80a2c8 into docker-library:main Jan 26, 2024
1 check passed
@yosifkit yosifkit deleted the meta-refactor branch January 26, 2024 00:21
rm temp.tar
jq '
.manifests |= (
del(.[].annotations)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why are the annotations deleted?

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

@whalelines whalelines Jan 26, 2024

Choose a reason for hiding this comment

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

Then why do we add them in the build? (Sorry for my ignorance)

Copy link
Member Author

Choose a reason for hiding this comment

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

So that they show up in the provenance data 😅

"mkdir temp",
"tar -xvf temp.tar -C temp",
"rm temp.tar",
# munge the index to what crane wants ("Error: layout contains 5 entries, consider --index")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps something to do with this?

Copy link
Member Author

@tianon tianon Jan 26, 2024

Choose a reason for hiding this comment

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

Correct -- because of the limitations of an OCI layout as a docker save format, the output from docker buildx build --output type=tar generates an index.json with a new entry for every --tag flag:

$ docker buildx build --builder foo --quiet --output type=oci - <<<$'FROM scratch\nCMD []' --tag foo --tag bar --tag baz | tar --extract --to-stdout index.json | jq
{
  "schemaVersion": 2,
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:1be03c71b27e7950b1a52e029ad139847a0771de9d2705ae8ab3742cd7d91ad6",
      "size": 288,
      "annotations": {
        "io.containerd.image.name": "docker.io/library/foo:latest",
        "org.opencontainers.image.created": "2024-01-26T18:48:33Z",
        "org.opencontainers.image.ref.name": "latest"
      },
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:1be03c71b27e7950b1a52e029ad139847a0771de9d2705ae8ab3742cd7d91ad6",
      "size": 288,
      "annotations": {
        "io.containerd.image.name": "docker.io/library/bar:latest",
        "org.opencontainers.image.created": "2024-01-26T18:48:33Z",
        "org.opencontainers.image.ref.name": "latest"
      },
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:1be03c71b27e7950b1a52e029ad139847a0771de9d2705ae8ab3742cd7d91ad6",
      "size": 288,
      "annotations": {
        "io.containerd.image.name": "docker.io/library/baz:latest",
        "org.opencontainers.image.created": "2024-01-26T18:48:33Z",
        "org.opencontainers.image.ref.name": "latest"
      },
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    }
  ]
}

Because the annotations are where the unique tags are stored, if we delete those, then unique can give us a single entry instead:

$ docker buildx build --builder foo --quiet --output type=oci - <<<$'FROM scratch\nCMD []' --tag foo --tag bar --tag baz | tar --extract --to-stdout index.json | jq '.manifests |= (del(.[].annotations) | unique)'
{
  "schemaVersion": 2,
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:1be03c71b27e7950b1a52e029ad139847a0771de9d2705ae8ab3742cd7d91ad6",
      "size": 288,
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    }
  ]
}

And now again, but this time with --provenance turned on (so we get an image index instead of an image manifest -- note the mediaType field in the descriptor):

$ docker buildx build --builder foo --provenance=mode=max --no-cache --quiet --output type=oci - <<<$'FROM hello-world' --tag foo --tag bar --tag baz | tar --extract --to-stdout index.json | jq '.manifests |= (del(.[].annotations) | unique)'
{
  "schemaVersion": 2,
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.index.v1+json",
      "digest": "sha256:a3cd4b5d34fcc7fe9ae1f6a9fd5459b7297e6cee7f6a5b200b715932a0fcb246",
      "size": 855
    }
  ]
}

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