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

Add crane flatten #1104

Merged
merged 5 commits into from
Aug 12, 2021
Merged

Add crane flatten #1104

merged 5 commits into from
Aug 12, 2021

Conversation

jonjohnsonjr
Copy link
Collaborator

@jonjohnsonjr jonjohnsonjr commented Aug 12, 2021

This is adapted from #735 but changes the UX a bit to match what we've come to expect from crane.

Add pkg/crane.Upload as well, for uploading a layer.

Closes #1103


$ crane manifest gcr.io/kaniko-project/executor | jq .
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "size": 3707,
    "digest": "sha256:1c812ffa8ec16797474d59cdb7667439e6bc26eb6054f7257b9016bdbc452d11"
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 14219823,
      "digest": "sha256:94ed89128ee0d8b28f7cf724c516e51c041424c4bd5bb125fecfeeb76307eb9c"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 4523491,
      "digest": "sha256:a804545c4b2ee9188580e438a3b56db29aad1af748ec2ec0c3d1d5e5fc55b538"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 2964519,
      "digest": "sha256:0f9a0bccd2dc597ec892a7f3e255b14c7c1fd0800cd173f2126a2dda3e519f91"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 6563884,
      "digest": "sha256:5d7f42cbc20d9b6bcf306b4402940b4aabc0e655273ee6832814fcc99c3ebfee"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 357642,
      "digest": "sha256:16f9858f396996c895a2ad07bdca08f3ec724e5485688e3cda31f8c3fca014c5"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 153,
      "digest": "sha256:f5f0d1ae165026c9094a1fca5f5f9f488cd19fffb6d0d7a7bc94e8c486fab7ad"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 540,
      "digest": "sha256:cc48692dd99f82f2708b30beed23974456ff65c9b3c1b5394e17df7fd39460ac"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 132,
      "digest": "sha256:b9a35a76a8f42260e1a25d274acc94dedac2b8d85b117d428e8491b5ea526184"
    },
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 339,
      "digest": "sha256:f68c2840c45f74cc7e3fedc214f88ac76252fd1f5e6e16008fa01d74c08d8f85"
    }
  ]
}
$ crane flatten gcr.io/kaniko-project/executor -t gcr.io/jonjohnson-test/kaniko:flattened
2021/08/11 17:03:23 pushed blob: sha256:90a1ce29e3c1e97127cbd84238973006c669f79c4608974e4d23dd96dfaa246a
2021/08/11 17:03:25 pushed blob: sha256:748697bc98d140e2fef5aaac09361e65ee9ec230d0dd3860d42b991150d47e06
2021/08/11 17:03:26 gcr.io/jonjohnson-test/kaniko:flattened: digest: sha256:e55cacb041826deefc92f2740d3bc4742c8b9597e587efa43fa4b7fe89127f64 size: 429
gcr.io/jonjohnson-test/kaniko@sha256:e55cacb041826deefc92f2740d3bc4742c8b9597e587efa43fa4b7fe89127f64
$ crane manifest gcr.io/jonjohnson-test/kaniko:flattened | jq .
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "size": 3419,
    "digest": "sha256:748697bc98d140e2fef5aaac09361e65ee9ec230d0dd3860d42b991150d47e06"
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 28533261,
      "digest": "sha256:90a1ce29e3c1e97127cbd84238973006c669f79c4608974e4d23dd96dfaa246a"
    }
  ]
}

Note that we preserve the original history in comment and what was flattened in the created_by comment. I'm not sure if we actually want to include the original image ref, or if we should just include the original image digest here to make this more reproducible.

$ crane config gcr.io/jonjohnson-test/kaniko:flattened | jq .
{
  "architecture": "amd64",
  "created": "2021-05-19T20:00:47.261095682Z",
  "history": [
    {
      "created": "0001-01-01T00:00:00Z",
      "created_by": "crane flatten sha256:6ecc43ae139ad8cfa11604b592aaedddcabff8cef469eda303f1fb5afe5e3034",
      "comment": "[{\"created\":\"2021-05-19T20:00:46.895205234Z\",\"created_by\":\"COPY /go/src/github.com/GoogleContainerTools/kaniko/out/executor /kaniko/executor # buildkit\",\"comment\":\"buildkit.dockerfile.v0\"},{\"created\":\"2021-05-19T20:00:46.929792602Z\",\"created_by\":\"COPY /usr/local/bin/docker-credential-gcr /kaniko/docker-credential-gcr # buildkit\",\"comment\":\"buildkit.dockerfile.v0\"},{\"created\":\"2021-05-19T20:00:46.958575143Z\",\"created_by\":\"COPY /go/src/github.com/awslabs/amazon-ecr-credential-helper/bin/local/docker-credential-ecr-login /kaniko/docker-credential-ecr-login # buildkit\",\"comment\":\"buildkit.dockerfile.v0\"},{\"created\":\"2021-05-19T20:00:46.994104887Z\",\"created_by\":\"COPY /go/src/github.com/chrismellard/docker-credential-acr-env/build/docker-credential-acr-env /kaniko/docker-credential-acr # buildkit\",\"comment\":\"buildkit.dockerfile.v0\"},{\"created\":\"2021-05-19T20:00:47.010924888Z\",\"created_by\":\"COPY /ca-certificates.crt /kaniko/ssl/certs/ # buildkit\",\"comment\":\"buildkit.dockerfile.v0\"},{\"created\":\"2021-05-19T20:00:47.026599082Z\",\"created_by\":\"COPY /kaniko/.docker /kaniko/.docker # buildkit\",\"comment\":\"buildkit.dockerfile.v0\"},{\"created\":\"2021-05-19T20:00:47.03965574Z\",\"created_by\":\"COPY files/nsswitch.conf /etc/nsswitch.conf # buildkit\",\"comment\":\"buildkit.dockerfile.v0\"},{\"created\":\"2021-05-19T20:00:47.051870289Z\",\"created_by\":\"ENV HOME=/root\",\"comment\":\"buildkit.dockerfile.v0\",\"empty_layer\":true},{\"created\":\"2021-05-19T20:00:47.051870289Z\",\"created_by\":\"ENV USER=root\",\"comment\":\"buildkit.dockerfile.v0\",\"empty_layer\":true},{\"created\":\"2021-05-19T20:00:47.051870289Z\",\"created_by\":\"ENV PATH=/usr/local/bin:/kaniko\",\"comment\":\"buildkit.dockerfile.v0\",\"empty_layer\":true},{\"created\":\"2021-05-19T20:00:47.051870289Z\",\"created_by\":\"ENV SSL_CERT_DIR=/kaniko/ssl/certs\",\"comment\":\"buildkit.dockerfile.v0\",\"empty_layer\":true},{\"created\":\"2021-05-19T20:00:47.051870289Z\",\"created_by\":\"ENV DOCKER_CONFIG=/kaniko/.docker/\",\"comment\":\"buildkit.dockerfile.v0\",\"empty_layer\":true},{\"created\":\"2021-05-19T20:00:47.051870289Z\",\"created_by\":\"ENV DOCKER_CREDENTIAL_GCR_CONFIG=/kaniko/.config/gcloud/docker_credential_gcr_config.json\",\"comment\":\"buildkit.dockerfile.v0\",\"empty_layer\":true},{\"created\":\"2021-05-19T20:00:47.051870289Z\",\"created_by\":\"WORKDIR /workspace\",\"comment\":\"buildkit.dockerfile.v0\"},{\"created\":\"2021-05-19T20:00:47.261095682Z\",\"created_by\":\"RUN docker-credential-gcr config --token-source=env # buildkit\",\"comment\":\"buildkit.dockerfile.v0\"},{\"created\":\"2021-05-19T20:00:47.261095682Z\",\"created_by\":\"ENTRYPOINT [\\\"/kaniko/executor\\\"]\",\"comment\":\"buildkit.dockerfile.v0\",\"empty_layer\":true}]"
    }
  ],
  "os": "linux",
  "rootfs": {
    "type": "layers",
    "diff_ids": [
      "sha256:67bf165867562b1841e1255e879e60340484743d8a3bceddb93c488c0379e0d1"
    ]
  },
  "config": {
    "Entrypoint": [
      "/kaniko/executor"
    ],
    "Env": [
      "PATH=/usr/local/bin:/kaniko",
      "HOME=/root",
      "USER=root",
      "SSL_CERT_DIR=/kaniko/ssl/certs",
      "DOCKER_CONFIG=/kaniko/.docker/",
      "DOCKER_CREDENTIAL_GCR_CONFIG=/kaniko/.config/gcloud/docker_credential_gcr_config.json"
    ],
    "WorkingDir": "/workspace"
  }
}

This is adapted from google#735 but changes the UX a bit to match what we've
come to expect from crane.

Add pkg/crane.Upload as well, for uploading a layer.
@codecov-commenter
Copy link

codecov-commenter commented Aug 12, 2021

Codecov Report

Merging #1104 (fb4d2f0) into main (bcbf8d3) will increase coverage by 0.02%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1104      +/-   ##
==========================================
+ Coverage   75.41%   75.44%   +0.02%     
==========================================
  Files         108      108              
  Lines        7685     7692       +7     
==========================================
+ Hits         5796     5803       +7     
  Misses       1334     1334              
  Partials      555      555              
Impacted Files Coverage Δ
pkg/crane/push.go 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update bcbf8d3...fb4d2f0. Read the comment docs.

@jonjohnsonjr
Copy link
Collaborator Author

Re: reproducibility... a stupid idea:

If the original image ref is by digest, we could include only the digest in the created_by string. If it's by tag, we could include everything (repo:tag@digest).

It's a weak heuristic, but I think pretty okay. The only issue is if someone is flattening by digest and wants the original image ref, we'd exclude it.

cmd/crane/cmd/flatten.go Outdated Show resolved Hide resolved
Comment on lines 101 to 104
// If the new ref isn't provided, write over the original image.
// If that ref was provided by digest (e.g., output from
// another crane command), then strip that and push the
// mutated image by digest instead.
Copy link
Collaborator

Choose a reason for hiding this comment

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

In #960 if you rebase by digest we'll push to :rebased unless you tell us what to push to. I don't love it, but I especially don't love it if it's going to disagree with the UX of crane flatten <img-by-digest>.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't love that either, can do the same thing in #960 that we do here?

log.Fatalf("parsing %s: %v", newRef, err)
}
if _, ok := r.(name.Digest); ok {
// If we're pushing by digest, we need to upload the layer first.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is because the stream.Layer's digest won't be known until it's uploaded, right? Does pushing to some fallback tag instead help here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'd rather not push to a fallback tag because that might overwrite an existing tag or pollute the registry.

@imjasonh
Copy link
Collaborator

Can/should we detect and unset base image annotations from the flattened image?

@jonjohnsonjr
Copy link
Collaborator Author

Can/should we detect and unset base image annotations from the flattened image?

I'd lean towards no. The base image is still the same, because in theory this is an equivalent but flattened image. If you wanted to rebuild based on the base changing, you could do rebuild && flatten. You could argue that the original image is the base image, but I'm not sure if we want to assume that.

Comment on lines +52 to +71
// Stupid hack to support insecure flag.
nameOpt := []name.Option{}
if ok, err := cmd.Parent().PersistentFlags().GetBool("insecure"); err != nil {
log.Fatalf("flag problems: %v", err)
} else if ok {
nameOpt = append(nameOpt, name.Insecure)
}
r, err := name.ParseReference(newRef, nameOpt...)
if err != nil {
log.Fatalf("parsing %s: %v", newRef, err)
}

desc, err := crane.Head(ref, *options...)
if err != nil {
log.Fatalf("checking %s: %v", ref, err)
}
if !cmd.Parent().PersistentFlags().Changed("platform") && desc.MediaType.IsIndex() {
log.Fatalf("flattening an index is not yet supported")
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

brb stealing these 😄

@jonjohnsonjr jonjohnsonjr merged commit bea59b9 into google:main Aug 12, 2021
@jonjohnsonjr jonjohnsonjr deleted the flatten branch August 12, 2021 18:49
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.

None yet

3 participants