Skip to content

Commit cbd4dee

Browse files
author
Natalie Arellano
committed
Break up Buildpack API section into separate "how to" pages
Signed-off-by: Natalie Arellano <[email protected]>
1 parent f782d78 commit cbd4dee

File tree

14 files changed

+431
-404
lines changed

14 files changed

+431
-404
lines changed

content/docs/.common/concepts/extension.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ provide. By contrast, Dockerfiles are the most-used and best-understood mechanis
3434
installing OS-level dependencies for containers.
3535

3636
The CNB Dockerfiles feature allows Dockerfiles to "provide" dependencies that buildpacks "require" through a
37-
shared [build plan](/docs/reference/spec/buildpack-api/#build-plan), by introducing the concept of image extensions.
37+
shared [build plan], by introducing the concept of image extensions.
3838

3939
## What do they look like?
4040

@@ -67,7 +67,7 @@ The extension determines if it is needed or not.
6767

6868
Like buildpacks, extensions participate in the `detect` phase - analyzing application source code to determine if they
6969
are needed. During `detect`, extensions can contribute to
70-
the [build plan](/docs/reference/spec/buildpack-api/#build-plan) - recording dependencies that they are able to "
70+
the [build plan] - recording dependencies that they are able to "
7171
provide" (though unlike buildpacks, they can't "require" anything).
7272

7373
If the provided order contains extensions, the output of `detect` will be a group of image extensions and a group of
@@ -80,3 +80,5 @@ The extension outputs Dockerfiles that can be used to extend either or both of t
8080

8181
For more information and to see a build in action,
8282
see [authoring an image extension](/docs/for-buildpack-authors/tutorials/basic-extension).
83+
84+
[build plan]: /docs/for-buildpack-authors/how-to/write-buildpacks/use-build-plan
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
+++
2+
title="Craft a buildpack order"
3+
weight=99
4+
+++
5+
6+
<!--more-->
7+
8+
This page is a stub! The CNB project is applying to [Google Season of Docs](https://developers.google.com/season-of-docs/docs/timeline) to receive support for improving our documentation. Please check back soon.
9+
10+
If you are familiar with this content and would like to make a contribution, please feel free to open a PR :)

content/docs/for-buildpack-authors/how-to/write-buildpacks/create-layer.md

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,45 @@ title="Create dependency layers"
33
weight=99
44
+++
55

6+
Each directory created by the buildpack under the `CNB_LAYERS_DIR` can be used as a layer in the final image or build cache.
7+
68
<!--more-->
79

8-
This page is a stub! The CNB project is applying to [Google Season of Docs](https://developers.google.com/season-of-docs/docs/timeline) to receive support for improving our documentation. Please check back soon.
10+
That is, each directory can be used for any of the following purposes:
11+
12+
* Launch - the directory will be included in the run image as a single layer
13+
* Cache - the directory will be included in the cache and restored on future builds
14+
* Build - the directory will be accessible by subsequent buildpacks
15+
16+
A buildpack defines how a layer will by used by creating a `<layer>.toml`
17+
with a name matching the directory it describes in the `CNB_LAYERS_DIR`.
18+
19+
For example, a buildpack might create a `$CNB_LAYERS_DIR/python` directory
20+
and a `$CNB_LAYERS_DIR/python.toml` with the following contents:
21+
22+
```
23+
launch = true
24+
cache = true
25+
build = true
26+
```
27+
28+
In this example, the `python` directory will be included in the run image,
29+
cached for future builds, and will be accessible to subsequent buildpacks via the environment.
30+
31+
### Example
32+
33+
This is a simple example of a buildpack that runs Python's `pip` package manager
34+
to resolve dependencies:
35+
36+
```
37+
#!/bin/sh
38+
39+
PIP_LAYER="$CNB_LAYERS_DIR/pip"
40+
mkdir -p "$PIP_LAYER/modules" "$PIP_LAYER/env"
41+
42+
pip install -r requirements.txt -t "$PIP_LAYER/modules" \
43+
--install-option="--install-scripts=$PIP_LAYER/bin" \
44+
--exists-action=w --disable-pip-version-check --no-cache-dir
945
10-
If you are familiar with this content and would like to make a contribution, please feel free to open a PR :)
46+
echo "launch = true" > "$PIP_LAYER.toml"
47+
```
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
+++
2+
title="Get started"
3+
weight=0
4+
+++
5+
6+
To write a buildpack, we follow the [Buildpack Specification](https://github.com/buildpacks/spec/blob/main/buildpack.md),
7+
which defines the contract between buildpacks and the lifecycle.
8+
9+
<!--more-->
10+
11+
A buildpack must contain three files:
12+
13+
* `buildpack.toml`
14+
* `bin/detect`
15+
* `bin/build`
16+
17+
The two files in `bin/` must be executable.
18+
They can be shell scripts written in a language like Bash,
19+
or they can be executables compiled from a language like Go.
20+
21+
## `buildpack.toml`
22+
23+
A buildpack must contain a `buildpack.toml` file in its root directory.
24+
25+
### Example
26+
27+
```
28+
api = "0.10"
29+
30+
[buildpack]
31+
id = "example.com/python"
32+
version = "1.0"
33+
34+
# Targets the buildpack will work with
35+
[[targets]]
36+
os = "linux"
37+
38+
# Stacks (deprecated) the buildpack will work with
39+
[[stacks]]
40+
id = "io.buildpacks.stacks.jammy"
41+
```
42+
43+
For more information, see [buildpack config](/docs/reference/config/buildpack-config).
44+
45+
## `bin/detect`
46+
47+
### Usage
48+
49+
```
50+
bin/detect
51+
```
52+
53+
### Summary
54+
55+
`bin/detect` is used to determine if a buildpack can work with a given codebase.
56+
It will often check for the existence of a particular file,
57+
or some configuration indicating what kind of application has been provided.
58+
59+
Two environment variables identify important file system paths:
60+
61+
* `CNB_PLATFORM_DIR` - a directory containing platform provided configuration, such as environment variables.
62+
* `CNB_BUILD_PLAN_PATH` - a path to a file containing the [build plan].
63+
64+
In addition, the working directory for `bin/detect` is the application directory.
65+
66+
`bin/detect` must return an exit code of `0` if the codebase can be serviced by this buildpack,
67+
and `100` if it cannot.
68+
Other exit codes indicate an error during detection.
69+
70+
### Example
71+
72+
This is a simple example of a buildpack that detects a Python application
73+
by checking for the presence of a `requirements.txt` file:
74+
75+
```
76+
#!/bin/sh
77+
78+
if [ -f requirements.txt ]; then
79+
echo "Python Buildpack"
80+
exit 0
81+
else
82+
exit 100
83+
fi
84+
```
85+
86+
## `bin/build`
87+
88+
### Usage
89+
90+
```
91+
bin/build
92+
```
93+
94+
`bin/build` does (all or part of) the work of transforming application source code into a runnable artifact.
95+
It will often resolve dependencies, install binary packages, and compile code.
96+
Three environment variables identify important file system paths:
97+
98+
* `CNB_LAYERS_DIR` - a directory that may contain subdirectories representing each layer created by the buildpack in the final image or build cache.
99+
* `CNB_PLATFORM_DIR` - a directory containing platform provided configuration, such as environment variables.
100+
* `CNB_BP_PLAN_PATH` - a path to a file containing the [build plan].
101+
102+
In addition, the working directory for `bin/build` is the application directory.
103+
104+
All changes to the codebase in the working directory will be persisted in the final image,
105+
along with any launch layers created in the `CNB_LAYERS_DIR`.
106+
107+
It is important to note that multiple buildpacks may work together to create the final image,
108+
each contributing a subset of the dependencies or configuration needed to run the application.
109+
In this way, buildpacks are modular and composable.
110+
111+
[build plan]: /docs/for-buildpack-authors/how-to/write-buildpacks/use-build-plan

content/docs/for-buildpack-authors/how-to/write-buildpacks/use-build-plan.md

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,119 @@ title="Use the build plan"
33
weight=99
44
+++
55

6+
The [Build Plan](https://github.com/buildpacks/spec/blob/main/buildpack.md#build-plan-toml) is a document that buildpacks can use to pass information between the `detect` and `build` phases, and between each other.
7+
The build plan is passed (by the lifecycle) as a parameter to the `detect` and `build` binaries of each buildpack.
8+
69
<!--more-->
710

8-
This page is a stub! The CNB project is applying to [Google Season of Docs](https://developers.google.com/season-of-docs/docs/timeline) to receive support for improving our documentation. Please check back soon.
11+
During the `detect` phase, each buildpack may write something it `requires` or `provides` (or both) into the Build Plan.
12+
A buildpack can `require` or `provide` multiple dependencies, and even multiple groupings of dependencies (using `or` lists).
13+
Additionally, multiple buildpacks may `require` or `provide` the same dependency.
14+
For detailed information, consult the [spec](https://github.com/buildpacks/spec/blob/main/buildpack.md#buildpack-plan-toml).
15+
16+
The lifecycle uses the Build Plan to determine whether a particular list of buildpacks can work together,
17+
by seeing whether all dependencies required can be provided by that list.
18+
19+
Later, during the `build` phase, each buildpack may read the Buildpack Plan (a condensed version of the Build Plan, composed by the lifecycle) to determine what it should do.
20+
21+
Let's see how this works with an example.
22+
23+
### Example: `node-engine` buildpack
24+
25+
Let's walk through some possible cases a `node-engine` buildpack may consider:
26+
27+
1. Nothing in the app explicitly calls out that it is needed
28+
2. It is explicitly referred to in some configuration file
29+
30+
We will also consider what an `NPM` and a `JVM` buildpack may do.
31+
32+
#### Scenario 1: No Explicit Request
33+
34+
A `node-engine` buildpack is always happy to `provide` the `node` dependency. The build plan it will write may look something like:
35+
```
36+
[[provides]]
37+
name = "node"
38+
```
39+
> **NOTE:** If this was the only buildpack running, this would fail the `detect` phase. In order to pass, every `provides` must be matched up with a `requires`, whether in the same buildpack or in another buildpack.
40+
> See the [spec](https://github.com/buildpacks/spec/blob/main/buildpack.md#phase-1-detection) for particulars on how ordering buildpacks can adjust detection results.
41+
42+
#### Scenario 2: One Version Requested
43+
44+
During the `detect` phase, the `node-engine` buildpack sees in one configuration file (e.g. a `.nvmrc` file in the app directory) that `node v10.x` is explicitly requested by the application. Seeing that, it may write the below text to the build plan:
45+
```
46+
[[provides]]
47+
name = "node"
48+
49+
[[requires]]
50+
name = "node"
51+
version = "10.x"
52+
53+
[requires.metadata]
54+
version-source = ".nvmrc"
55+
```
56+
57+
As always, the buildpack `provides` `node`. In this particular case, a version of `node` (`10.x`) is being requested in a configuration file (`.nvmrc`). The buildpack chooses to add an additional piece of metadata (`version-source`), so that it can understand where that request came from.
58+
59+
#### NPM Buildpack
60+
61+
`NPM` is the default package manager for `node`. A NPM Buildpack may ensure that all the packages for the application are present (by running `npm install`), and perhaps cache those packages as well, to optimize future builds.
62+
63+
NPM is typically distributed together with node. As a result, a NPM buildpack may require `node`, but not want to `provide` it, trusting that the `node-engine` buildpack will be in charge of `providing` `node`.
64+
65+
The NPM buildpack could write the following to the build plan, if the buildpack sees that `npm` is necessary (e.g., it sees a `package.json` file in the app directory):
66+
```
67+
[[requires]]
68+
name = "node"
69+
```
70+
71+
If, looking in the `package.json` file, the NPM buildpack sees a specific version of `node` requested in the [engines](https://docs.npmjs.com/files/package.json#engines) field (e.g. `14.1`), it may write the following to the build plan:
72+
```
73+
[[requires]]
74+
name = "node"
75+
version = "14.1"
76+
77+
[requires.metadata]
78+
version-source = "package.json"
79+
```
80+
81+
> **NOTE:** As above, if this was the only buildpack running, this would fail the `detect` phase. In order to pass, every `provides` must be matched up with a `requires`, whether in the same buildpack or in another buildpack.
82+
> See the [spec](https://github.com/buildpacks/spec/blob/main/buildpack.md#phase-1-detection) for particulars on how ordering buildpacks can adjust detection results.
83+
84+
However, if the NPM Buildpack was run together with the Node Engine buildpack (which `provides` `node`), the lifecycle will see that all requirements are fulfilled, and select that group as the correct set of buildpacks.
85+
86+
### Example: JVM buildpack
87+
88+
Java is distributed in two formats - the `jdk` (Java Development Kit), which allows for compilation and running of Java programs, and the `jre` (Java Runtime Environment, which allows for running compiled Java programs).
89+
A very naive implementation of the buildpack may have it write several `provides` options to the build plan, detailing everything that it can provide,
90+
while later buildpacks would figure out based on the application which options it requires, and would `require` those.
91+
In this particular case, we can use the `or` operator to present different possible build plans the buildpack can follow:
92+
93+
```
94+
# option 1 (`jre` and `jdk`)
95+
[[provides]]
96+
name = "jre"
97+
98+
[[provides]]
99+
name = "jdk"
100+
101+
# option 2 (or just `jdk`)
102+
[[or]]
103+
[[or.provides]]
104+
name = "jdk"
105+
106+
# option 3 (or just `jre`)
107+
[[or]]
108+
[[or.provides]]
109+
name = "jre"
110+
```
111+
112+
The buildpack gives three options to the lifecycle:
113+
* It can provide a standalone `jre`
114+
* It can provide a standalone `jdk`
115+
* It can provide both the `jdk` and `jre`
116+
117+
As with the other buildpacks, this alone will not be sufficient for the lifecycle. However, other buildpacks that follow may `require` certain things.
9118

10-
If you are familiar with this content and would like to make a contribution, please feel free to open a PR :)
119+
For example, another buildpack may look into the application and, seeing that it is a Java executable, `require` the `jre` in order to run it.
120+
When the lifecycle analyzes the results of the `detect` phase, it will see that there is a buildpack which provides `jre`, and a buildpack that requires `jre`,
121+
and will therefore conclude that those options represent a valid set of buildpacks.

content/docs/for-buildpack-authors/tutorials/basic-buildpack/04_build-app.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,4 @@ A new image named `test-node-js-app` was created in your Docker daemon with a la
110110
<a href="/docs/for-buildpack-authors/tutorials/basic-buildpack/05_make-app-runnable" class="button bg-pink">Next Step</a>
111111
<!--+end+-->
112112

113-
[layers-dir]: /docs/reference/spec/buildpack-api/#layers
113+
[layers-dir]: /docs/for-buildpack-authors/how-to/write-buildpacks/create-layer

content/docs/for-buildpack-authors/tutorials/basic-extension/03_building-blocks-extension.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ You should see something akin to the following:
3434
API except where noted. Consult the [spec](https://github.com/buildpacks/spec/blob/main/image_extension.md)
3535
for further details.
3636
* `./bin/detect` is invoked during the `detect` phase. It analyzes application source code to determine if the extension
37-
is needed and contributes [build plan](/docs/reference/spec/buildpack-api/#build-plan) entries (much like a
37+
is needed and contributes [build plan] entries (much like a
3838
buildpack `./bin/detect`). Just like for buildpacks, a `./bin/detect` that exits with code `0` is considered to have
3939
passed detection, and fails otherwise.
4040
* `./bin/generate` is invoked during the `generate` phase (a new lifecycle phase that happens after `detect`). It
@@ -51,3 +51,5 @@ For guidance around writing extensions and more advanced use cases, see [here](/
5151

5252
<a href="/docs/for-buildpack-authors/tutorials/basic-extension/04_build-dockerfile" class="button bg-pink">Next Step</a>
5353
<!--+ end +-->
54+
55+
[build plan]: /docs/for-buildpack-authors/how-to/write-buildpacks/use-build-plan
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
+++
22
title="Configuration"
33
include_summaries=true
4-
54
+++

content/docs/reference/config/builder-config.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
+++
22
title="builder.toml"
3-
summary="Schema of the builder config file."
43
aliases=[
54
"/docs/reference/builder-config/"
65
]
6+
weight=2
77
+++
88

9-
A [builder][builder] configuration schema is as follows:
9+
The builder config file is used for creating [builders][builder].
10+
11+
<!--more-->
12+
13+
The schema is as follows:
1014

1115
- #### `description` _(string, optional)_
1216
A human-readable description of the builder, to be shown in `builder inspect` output
@@ -26,7 +30,7 @@ A [builder][builder] configuration schema is as follows:
2630

2731
- #### `order` _(list, required)_
2832
A list of buildpack groups. This list determines the order in which groups of buildpacks
29-
will be tested during detection. Detection is a phase of the [lifecycle][lifecycle] where
33+
will be tested during detection. Detection is a phase of the [lifecycle] where
3034
buildpacks are tested, one group at a time, for compatibility with the provided application source code. The first
3135
group whose non-optional buildpacks all pass detection will be the group selected for the remainder of the build. Each
3236
group currently contains a single required field:
@@ -85,7 +89,7 @@ A [builder][builder] configuration schema is as follows:
8589
[Run image mirrors](/docs/for-app-developers/concepts/base-images/run#run-image-mirrors) for the stack
8690

8791
- #### `lifecycle` _(optional)_
88-
The [lifecycle][lifecycle] to embed into the builder. It must contain **at most one** the following fields:
92+
The [lifecycle] to embed into the builder. It must contain **at most one** the following fields:
8993

9094
- **`version`** _(string, optional)_\
9195
The version of the lifecycle (semver format) to download. If specified, `uri` must not be provided.

0 commit comments

Comments
 (0)