...

Text file src/github.com/google/go-containerregistry/cmd/crane/rebase.md

Documentation: github.com/google/go-containerregistry/cmd/crane

     1### This code is experimental and might break you if not used correctly.
     2
     3The `rebase` command efficiently rewrites an image to replace the base image it
     4is `FROM` with a new base image.
     5
     6![rebase visualization](./rebase.png)
     7
     8([link](https://docs.google.com/drawings/d/1w8UxTZDRbDWVoqnbr17SJuU73pRxpOmOk_vzmC9WB2k/edit))
     9
    10**This is not safe in general**, but it can be extremely useful for platform
    11providers, e.g. when a vulnerability is discovered in a base layer and many
    12thousands or millions of applications need to be patched in a short period of
    13time.
    14
    15A commonly accepted guideline for rebase-safety is ABI-compatibility, but this
    16is still imperfect in a handful of ways, and the exact contract varies between
    17platform providers.
    18
    19Rebasing is best suited for when rebuilding is either impossible (source is not
    20available) or impractical (too much work, too little time).
    21
    22## Using `crane rebase`
    23
    24For purposes of illustration, imagine you've built a container image
    25`my-app:latest`, which is `FROM ubuntu`:
    26
    27```
    28FROM ubuntu
    29
    30RUN ./very-expensive-build-process.sh
    31
    32ENTRYPOINT ["/bin/myapp"]
    33```
    34
    35A serious vulnerability has been found in the `ubuntu` base image, and a new
    36patched version has been released, tagged as `ubuntu:latest`.
    37
    38You could build your app image again, and the Dockerfile's `FROM ubuntu`
    39directive would pick up the new base image release, but that requires a full
    40rebuild of your entire app from source, which might take a long time, and might
    41pull in other unrelated changes in dependencies.
    42
    43You may have thousands of images containing the vulnerability. You just want to
    44release this critical bug fix across all your apps, as quickly as possible.
    45
    46Instead, you could use `crane rebase` to replace the vulnerable base image
    47layers in your image with the patched base image layers, without requiring a
    48full rebuild from source.
    49
    50```
    51$ crane rebase my-app:latest \
    52  --old_base=ubuntu@sha256:deadbeef... \
    53  --new_base=ubuntu:latest \
    54  --tag=my-app:rebased
    55```
    56
    57This command:
    58
    591. fetches the manifest for the original image `my-app:latest`, and the
    60   `old_base` and `new_base` images
    611. checks that the original image is indeed based on `old_base`
    621. removes `old_base`'s layers from the original image
    631. replaces them with `new_base`'s layers
    641. computes and uploads a new manifest for the image, tagged as `--tag`.
    65
    66If `--tag` is not specified, its value will be assumed to be the original
    67image's name. If the original image was specified by digest, the resulting
    68image will be pushed by digest only.
    69
    70`crane rebase` will print the rebased image name by digest to `stdout`.
    71
    72### Base Image Annotation Hints
    73
    74The OCI image spec includes some [standard image
    75annotations](https://github.com/opencontainers/image-spec/blob/main/annotations.md)
    76that can provide hints for the `--old_base` and `--new_base` flag values, so
    77these don't need to be specified:
    78
    79- **`org.opencontainers.image.base.digest`** specifies the original digest of
    80  the base image
    81- **`org.opencontainers.image.base.name`** specifies the original base image's
    82  reference
    83
    84If the original image has these annotations, you can omit the `--old_base` and
    85`--new_base` flags, and their values will be assumed to be:
    86
    87- `--old_base`: the `base.name` annotation value, plus the `base.digest`
    88  annotation value
    89- `--new_base`: the `base.name` annotation value
    90
    91If these annotation values are invalid, and the flags aren't set, the operation
    92will fail.
    93
    94Whether or not the annotation values were set on the original image, they
    95_will_ be set on the resulting rebased image, to ease future rebase operations
    96on that image.
    97
    98`crane append` also supports the `--set-base-image-annotations` flag, which, if
    99true, will set these annotations on the resulting image.
   100
   101## Caveats
   102
   103The tool has no visibility into what the specific contents of the resulting
   104image, and has no idea what constitutes a "valid" image. As a result, it's
   105perfectly capable of producing an image that's entirely invalid garbage.
   106Rebasing arbitrary layers in an image is not a good idea.
   107
   108To help prevent garbage images, rebasing should only be done at a point in the
   109layer stack between "base" layers and "app" layers. These should adhere to some
   110contract about what "base" layers can be expected to produce, and what "app"
   111layers should expect from base layers.
   112
   113In the example above, for instance, we assume that the Ubuntu base image is
   114adhering to some contract with downstream app layers, that it won't remove or
   115drastically change what it provides to the app layer. If the `new_base` layers
   116removed some installed package, or made a breaking change to the version of
   117some compiler expected by the uppermost app layers, the resulting rebased image
   118might be invalid.
   119
   120In general, it's a good practice to tag rebased images to some other tag than
   121the `original` tag, perform some sanity checks, then tag the image to the
   122`original` tag once it's determined the image is valid.
   123
   124There is ongoing work to standardize and advertise base image contract
   125adherence to make rebasing safer.

View as plain text