---
# System prepended metadata

title: Extending Images UX
tags: [rfc]

---

---
tags: rfc
---

> TODO:
> - [ ] Add app developer use cases
> - [ ] Upgrade
> - [ ] Mixins


# Extending Images UX

The definition of an extended image is that of which an execution occurs within the running of a container to produce mutation to said image.


```
                        +-----+
                        |     |
                        |  e  |
                        |  x  |
                        |  t  |
                        |  e  |
                        |  n  |
+----------------+      |  s  |      +-----------------------+
|                |      |  i  |      |                       |
|   some/image   | +--> |  o  | +--> |  some/extended-image  |
|                |      |  n  |      |                       |
+----------------+      |     |      +-----------------------+
                        |  f  |
                        |  u  |
                        |  n  |
                        |  c  |
                        |     |
                        +-----+
```

Within the context of builders, it makes sense to provide this functionality to the following images:

- builder image
- run image

_We exclude build image because the builder is based (and therefor) effectively the build image but there is no technical limitation as to why they should be excluded._

An image can be extended if it adheres to the contract defined in [RFC #TBD](https://github.com/buildpacks/rfcs/blob/app-image-ext/text/0000-app-image-extensions.md#specification).

## Operators

The use cases this tries to solve are the following:

* As an operator, I want to produce a builder image that has package X installed from the OS.
* As an operator, I want to produce a run image that has package X installed from the OS.
* As an operator, I want to add OS packages to an existing builder image.
* As an operator, I want to add OS packages to an existing run image.

### `pack extend`: Extending any image

```shell
pack extend <image-name> [image-name, ...] --config extend.toml
```

where `extend.toml` is:

```toml
[extend]
image = "<image-name>"

[extend.metadata]
# arbitrary metadadata understood by the image being extended
```

The resulting image will contain the following information in a label `io.buildpacks.extend.metadata`. If the label exists on the image being extended it will be merged.

#### Example: Extenting run image

```shell
pack extend some/extended-run gcr.io/some/extended-run --config extend.toml
```

where `extend.toml` is:

```toml
[extend]
image = "some/run"

[extend.metadata]
packages = ["imagemagick"]
```

### `pack extend-builder`: Extending an existing builder

This case is more focused to extending all images associated with a builder. This includes the builder image and run image(s).

```shell
pack extend-builder \
    # name of image to save as
    # (required) *out*
    <image-name> \
    
    # configuration 
    # (required) *in*
    --extension-config <extend-builder.toml> \
    
    # name to save run image as
    # (required if `run` image is to be extended) *out*
    --run-image <image-name> \
    
    # name to save a run image mirror as
    # (optional) *out*
    --run-image-mirror <image-name>
```


`extend-builder.toml`:
```toml
[extend]
image = "<image-name>"

[extend.metadata]
# metadata provided to `run` and `build` images

[extend.metadata.run]
# metadata provided only to `run` images

[extend.metadata.build]
# metadata provided only to `build` images
```


#### Example: Extending a builder while saving only builder image

```shell
pack extend-builder some/extended-builder --extension-config extend.toml
```

where `extend.toml` is:

```toml
[extend]
image = "some/builder"

[extend.metadata.build]
packages = ["git"]
```

#### Example: Extending a builder while saving all images

```shell
pack extend-builder some/extended-builder \
    --run-image some/extended-run \
    --run-image-mirror gcr.io/some/extended-run \
    --config extend.toml
```

where `extend.toml` is:

```toml
[extend]
image = "some/builder"

[extend.metadata.run]
packages = ["imagemagick"]

[extend.metadata.build]
packages = ["build-essentials", "imagemagick"]
```

### Creating an extended builder

> Technically, leveraging the `pack extend` command instead of a new command could achieve the same thing without adding complexity to `create-builder`.

Adds configuration section and flags as defined in [`extend-builder`](#pack-extend-builder-Extending-an-existing-builder) to `pack create-builder`.

```shell
pack create-builder some/extended-builder \
    --run-image some/extended-run \
    --run-image-mirror gcr.io/some/extended-run \
    --config builder.toml
```

`builder.toml`:
```toml
[[buildpacks]]
# buildpacks to include in builder

[[order]]
[[order.group]]
# execution order of buildpacks

[stack]
id = "<stack-id>"
run-image = "<image-name>"
build-image = "<image-name>"

[extend]
[extend.metadata]
# metadata provided to `run` and `build` images

[extend.metadata.run]
# metadata provided only to `run` images

[extend.metadata.build]
# metadata provided only to `build` images
```