Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
262 changes: 153 additions & 109 deletions architecture/core_objects/builds.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,103 +10,145 @@
toc::[]

== Overview
A build is a process of transforming input parameters, typically source code, into a resulting object, typically a runnable image.
A build is the end result of transforming input parameters, typically source code, into a resulting object, typically a runnable image.

For a list of build commands, see the
link:../../dev_guide/builds.html[Developer's Guide].

== BuildConfig
The `BuildConfig` object is the definition of the entire build process. It consists of the following elements:
The `BuildConfig` object is the definition of the entire build process, and is dictated by link:../../dev_guide/builds.html#build-triggers[build triggers]:

[horizontal]
triggers:: Define policies used for automatically invoking builds:
GitHub webhooks::: GitHub specific webhooks that specify which repository
====
----
apiVersion: v1beta3
Copy link
Contributor

Choose a reason for hiding this comment

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

just a note, there will be v1 soon, but I think this applies to many other examples we have in docs... don't change it now, just a reminder

Copy link
Author

Choose a reason for hiding this comment

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

@mfojtik Good point. I've created an issue so that this can be remembered when the time comes: #428

kind: BuildConfig
metadata:
labels:
name: ruby-sample-build
template: application-template-stibuild
name: ruby-sample-build
namespace: ruby
resourceVersion: "7246"
selfLink: /osapi/v1beta3/namespaces/ruby/buildconfigs/ruby-sample-build
uid: 9c3d9693-0822-11e5-9deb-080027c5bfa9
spec:
output: <1>
to:
kind: ImageStreamTag
name: origin-ruby-sample:latest
resources: {} <2>
source: <3>
git:
uri: git://github.com/openshift/ruby-hello-world.git
type: Git
strategy: <4>
sourceStrategy:
from:
kind: ImageStreamTag
name: ruby-20-centos7:latest
incremental: true
type: Source
triggers:
- github: <5>
secret: secret101
type: github
- generic: <6>
secret: secret101
type: generic
- imageChange: <7>
lastTriggeredImageID: openshift/ruby-20-centos7:latest
type: imageChange

----
<1> *output* describes the resulting ImageStream source to which the
image should be pushed.
<2> *resources* describes the resource limits (cpu, memory) that should be used
by pods that run a build.
<3> *source* describes the SCM used to locate the sources. Currently only
supports Git.
<4> *strategy* describes which build type is invoked along with build type
specific details.
<5> *gitHub* triggers are Github-specific webhooks that specify which repository
changes, such as a new commit, should invoke a new build. This trigger is
specific to the GitHub API.
generic webhooks::: Similar to GitHub webhooks in that they invoke a new build
whenever it gets a notification. The difference is its payload is slightly
different than GitHub's.
image change::: Defines a trigger which is invoked upon availability of a new
image in the specified ImageRepository.

parameters::
source::: Describes the SCM used to locate the sources. Currently only supports
Git.
strategy::: Describes which build type is invoked along with build type specific
details.
output::: Describes the resulting image name, tag, and registry to which the
image should be pushed.
resources::: Describes the resource limits (cpu, memory) that should be used by pods that run a build.
<6> *generic* triggers are similar to GitHub webhooks in that they invoke a new
build when notified, but different in that the payload is slightly different
than GitHub's.
<7> *imageChange* triggers define a trigger which is invoked upon availability
of a new image in the specified ImageStream.
====

== Build Strategies

There are three available link:openshift_model.html#build-strategies[build strategies]:

* link:#docker-build[Docker build]
* link:#sti-build[STI build]
* link:#custom-build[Custom build]

The resulting object depends on which builder is used to create the image.
The resulting object depends on the builder used to create the image.

[#docker-build]
== Docker Build
Docker builds invoke the plain https://docs.docker.com/reference/commandline/cli/#build[docker build] command, and therefore expect a repository with a `Dockerfile` and all required directories.
=== Docker Build
Docker builds invoke the plain https://docs.docker.com/reference/commandline/cli/#build[docker build command], and therefore expect a repository with a *_Dockerfile_* and all required directories.

[#sti-build]
== STI Build
=== STI Build
link:../../creating_images/sti.html[Source-to-image (STI)] is a tool for
building reproducible Docker images. It produces ready-to-run images by
injecting a user source into a docker image and assembling a new docker image.
The new image incorporates the base image and built source, and is ready to use
with the `docker run` command. STI supports incremental builds which re-use
with the `docker run` command. STI supports incremental builds, which re-use
previously downloaded dependencies, previously built artifacts, etc.

*What are the goals of STI?*
The advantages of STI include:

[horizontal]
Image flexibility:: STI allows you to use almost any existing Docker image as
the base for your application. STI scripts can be written to layer application
code onto almost any existing Docker image, so you can take advantage of the
existing ecosystem. Note that currently STI relies on `tar` and `untar` to
inject application source so the image needs to be able to process tarred
content.

Speed:: Adding layers as part of a *_Dockerfile_* can be slow. With STI, the
assemble process can perform a large number of complex operations without
creating a new layer at each step. In addition, STI scripts can be written to
re-use dependencies stored in a previous version of the application image rather
than re-downloading them each time the build is run.

Patchability:: If an underlying image needs to be patched due to a security
issue, OpenShift can use STI to rebuild your application on top of the patched
builder image.
Image flexibility:: STI scripts can be written to layer application code onto
almost any existing Docker image, taking advantage of the existing ecosystem.
Note that, currently, STI relies on `tar` to inject application
source, so the image needs to be able to process tarred content.

Speed:: With STI, the assemble process can perform a large number of complex
operations without creating a new layer at each step, resulting in a fast
process. In addition, STI scripts can be written to re-use artifacts stored in a
previous version of the application image rather than having to download or
build them each time the build is run.

Patchability:: STI allows you to rebuild the application consistently if an
underlying image needs a patch due to a security issue

Operational efficiency:: By restricting build operations instead of allowing
arbitrary actions such as in a *_Dockerfile_*, the PaaS operator can avoid
arbitrary actions, such as in a *_Dockerfile_*, the PaaS operator can avoid
accidental or intentional abuses of the build system.

Operational security:: Allowing users to build arbitrary an *_Dockerfile_*
exposes the host system to root privilege escalation by a malicious user because
the entire docker build process is run as a user with docker privileges. STI
restricts the operations performed as a root user, and can run the scripts as an
individual user
Operational security:: Building an arbitrary *_Dockerfile_* exposes the host
system to root privilege escalation. This can be exploited by a malicious user
because the entire docker build process is run as a user with docker privileges.
STI restricts the operations performed as a root user, and can run the scripts
as an individual user.

User efficiency:: STI prevents developers from falling into a trap of performing
arbitrary `yum install` type operations during their application build, which
would result in slow development iteration.
User efficiency:: STI prevents developers from performing arbitrary `yum
install` type operations during their application build, which results in slow
development iteration.

Ecosystem:: Encourages a shared ecosystem of images with best practices you can
leverage for your applications.
Ecosystem:: STI encourages a shared ecosystem of images where you can leverage
best practices for your applications.

[#custom-build]
== Custom Build
Custom builds are the most sophisticated version of builds, allowing developers to define a builder image which is responsible for the entire process of the build. The custom builder image is a plain Docker image within which the author embeds the logic of the desired build process, such as building RPMs or building
base Docker images.
=== Custom Build
Custom builds allow developers to define the specific builder image responsible
for the entire build process. The custom builder image is a plain Docker image
with embedded build process logic, such as building RPMs or building base Docker
images.

[#using-docker-credentials-for-pushing-and-pulling-images]
== Using Docker Credentials for Pushing and Pulling Images

In case you want to push the output image into a private Docker Registry or pull
the builder image from the private Docker Registry that requires authentication
or Docker Hub, you have to supply the `.dockercfg` file with valid Docker
Registry credentials.
Supply the `.dockercfg` file with valid Docker Registry credentials in order to push the output image into a private Docker Registry or pull the
builder image from the private Docker Registry that requires authentication.

The *_.dockercfg_* JSON file usually exists in your home directory and has
The *_.dockercfg_* JSON file exists in your home directory by default and has
following format:

====
Expand All @@ -115,7 +157,7 @@ following format:
{
"https://index.docker.io/v1/": { <1>
"auth": "YWRfbGzhcGU6R2labnRib21ifTE=", <2>
"email": "foo@bar.com" <3>
"email": "user@example.com" <3>
}
}
----
Expand All @@ -125,17 +167,25 @@ following format:
<3> Email address for the login.
====

You can define multiple Docker registries entries in this file. You can also add
authentication entries to this file by running the `docker login` command. The
file will be created if it does not exist.
You can define multiple Docker registry entries in this file. Alternatively, you
can also add authentication entries to this file by running the `docker login`
command. The file will be created if it does not exist.

Kubernetes provides the
https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/design/secrets.md[Secret]
resource, which you can use to store your passwords and configuration. You must
create the `*Secret*` first before builds can use your *_.dockercfg_* file for
pushing the output image. The `*data*` field for the `*Secret*` object must
contain the `*dockercfg*` key with the value set to the base64-encoded content
of the *_.dockercfg_* file. For example:
resource, which is used to store your configuration and passwords. You must
first create the `*Secret*` before builds can use your *_.dockercfg_* file for
pushing the output image:

====
----
$ osc create -f secret.json
----
====

The `*data*` field for the `*Secret*` object must contain the `*dockercfg*` key
with the value set to the base64-encoded content of the *_.dockercfg_* file. For
example:

====

Expand All @@ -154,21 +204,12 @@ of the *_.dockercfg_* file. For example:
----
====

To create the `*Secret*` from a *_secret.json_* file, for example, you can use
the following command:
Once you have the `*Secret*` created, you can add a `PushSecret` field into the
`Output` section of the `BuildConfig` and set it to the name of the `*Secret*`
that you created, which in the above example is `*dockerhub*`:

====

----
$ osc create -f secret.json
----
====

Once you have the `*Secret*` created, you can add a `PushSecret` field into
`Output` section inside the `BuildConfig` and set it to the name of the
`*Secret*` that you created, in this case `*dockerhub*`.

```
"parameters": {
"output": {
"to": {
Expand All @@ -179,12 +220,14 @@ Once you have the `*Secret*` created, you can add a `PushSecret` field into
}
}
}
```
----
====

For pulling the builder Docker image from a private Docker registry, you have to specify
the `PullSecret` field, which is part of the build strategy definition:
Pull the builder Docker image from a private Docker registry by specifying the
`PullSecret` field, which is part of the build strategy definition:

```
====
----
{
"strategy": {
"stiStrategy": {
Expand All @@ -199,16 +242,17 @@ the `PullSecret` field, which is part of the build strategy definition:
"type": "STI"
}
}
```
----
====

[#using-private-repositories-for-builds]
== Using private repositories for builds
== Using Private Repositories for Builds

If you want to build your application from a private repository you must
supply valid credentials. Currently only SSH key based authentication is supported.
The keys used to access that repository live in `$HOME/.ssh/` directory.
They are usually named `id_dsa.pub`, `id_ecdsa.pub`, `id_ed25519.pub` or `id_rsa.pub`.
If you don't have any, you can generate them with the following command:
Supply valid credentials to build an application from a private repository.
Currently, only SSH key based authentication is supported. The repository keys
are located in the `$HOME/.ssh/` directory, and are named `id_dsa.pub`,
`id_ecdsa.pub`, `id_ed25519.pub` or `id_rsa.pub` by default. Generate SSH key
credentials with the following command:

====

Expand All @@ -217,18 +261,18 @@ $ ssh-keygen -t rsa -C "your_email@example.com"
----
====

Once that's done you're going to get two files: one containing your public key (as
explained above) and one containing a corresponding private key (one of `id_dsa`, `id_ecdsa`,
`id_ed25519` or `id_rsa`). With both of these in place you should consult your
source control management (SCM) system's manual on how to upload the public key.
The private one will be used to access your private repository.
Two files will be created: the public key (as explained above) and a
corresponding private key (one of `id_dsa`, `id_ecdsa`, `id_ed25519` or
`id_rsa`). With both of these in place you should consult your source control
management (SCM) system's manual on how to upload the public key. The private
key will be used to access your private repository.

Kubernetes provides the
The
https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/design/secrets.md[Secret]
resource, which you can use to store your keys. You must create the `*Secret*` first
before builds can use your ssh key for accessing your private repository.
The `*data*` field for the `*Secret*` object must contain your private key
with the value set to the base64-encoded content of that file. For example:
resource is used to store your keys. Create the `*Secret*` first before using
the ssh key to access the private repository. The `*data*` field for the
`*Secret*` object must contain your private key with the value set to the
base64-encoded content of that file:

====

Expand All @@ -238,8 +282,8 @@ $ base64 -w 0 $HOME/.ssh/id_rsa
----
====

Copy the value returned from `base64` command and paste it into `ssh-privatekey` field
in `*_secret.json_*` file:
Copy the value returned from the above command and place it into the
`ssh-privatekey` field in `*_secret.json_*` file:

====

Expand All @@ -258,18 +302,18 @@ in `*_secret.json_*` file:
----
====

You can then create the `*Secret*` from the *_secret.json_* file using the following command:
Then, create the `*Secret*` from the *_secret.json_* file using the following
command:

====

----
$ osc create -f secret.json
----
====

Once you have the `*Secret*` created, you can add a `SourceSecret` field into
`Source` section inside the `BuildConfig` and set it to the name of the
`*Secret*` that you created, in this case `*scmsecret*`:
Add a `SourceSecret` field into the `Source` section inside the `BuildConfig`
and set it to the name of the `*Secret*` that you created, in this case
`*scmsecret*`:

====

Expand Down