docs/builds.md
60b9d7ba
 # OpenShift Builds
893657fb
 
60b9d7ba
 ## Problem/Rationale
893657fb
 
60b9d7ba
 Kubernetes creates Docker containers from images that were built elsewhere and pushed to a Docker registry. Building Docker images is a foundational use-case in Docker-based workflows for application development and deployment. Without support for builds in Kubernetes, if a system administrator wanted a system that could build images, he or she would have to select a pre-existing build system or write a new one, and then figure out how to deploy and maintain it on or off Kubernetes. However, in most cases operators would wish to leverage the ability of Kubernetes to schedule task execution into a pool of available resources, and most build systems would want to take advantage of that mechanism.
893657fb
 
b6c660ef
 Offering an API for builds makes OpenShift a viable back-end for arbitrary third-party Docker image build systems which require resource constraints and scheduling capabilities, and allows organizations to orchestrate Docker builds from their existing continuous integration processes. OpenShift enables CI/CD flows around Docker images.
893657fb
 
60b9d7ba
 Most build jobs share common characteristics - a set of inputs to a build, the need to run a certain build process to completion, the capture of the logs from that build process, publishing resources from successful builds, and the final status of the build. In addition, the image-driven deployment flow that Kubernetes advocates depends on having images available.
893657fb
 
60b9d7ba
 Builds should take advantage of resource restrictions – specifying limitations on things such as CPU usage, memory usage, and build (pod) execution time – once support for this exists in Kubernetes. Additionally, builds should be repeatable and consistent (same inputs = same output).
893657fb
 
b6c660ef
 Although there are potentially several different types of builds that produce other types of output, OpenShift by default provides the ability to build Docker images.
893657fb
 
60b9d7ba
 Here are some possible user scenarios for builds in OpenShift:
893657fb
 
60b9d7ba
 1.   As a user of OpenShift, I want to build an image from a source URL and push it to a registry (for eventual deployment in OpenShift).
 2.   As a user of OpenShift, I want to build an image from a binary input (Docker context, artifact) and push it to a registry (for eventual deployment in OpenShift).
 3.   As a provider of a service that involves building Docker images, I want to offload the resource allocation, scheduling, and garbage collection associated with that activity to OpenShift instead of solving those problems myself.
 4.   As a developer of a system which involves building Docker images, I want to take advantage of OpenShift to perform the build, but orchestrate from an existing CI in order to integrate with my organization’s devops SOPs.
893657fb
 
60b9d7ba
 ### Example Use: Cloud IDE
893657fb
 
60b9d7ba
 Company X offers a Docker-based cloud IDE service and needs to build Docker images at scale for their customers’ hosted projects. Company X wants a turn-key solution for this that handles scheduling, resource allocation, and garbage collection. Using the build API, Company X can leverage OpenShift for the build work and concentrate on solving their core business problems.
893657fb
 
60b9d7ba
 ### Example Use: Enterprise Devops
893657fb
 
60b9d7ba
 Company Y wants to leverage OpenShift to build Docker images, but their Devops SOPs mandate the use of a third-party CI server in order to facilitate actions such as triggering builds when an upstream project is built and promoting builds when the result is signed off on in the CI server. Using the build API, company Y implements workflows in the CI server that orchestrate building in OpenShift which integrates with their organization’s SOPs.
893657fb
 
60b9d7ba
 ## Build Strategies
893657fb
 
bb70a2c5
 The OpenShift build system provides extensible support for build strategies based on selectable types specified in the build API. By default, two strategies are supported: Docker builds, and [Source-To-Images (s2i)](https://github.com/openshift/source-to-image#source-to-image-sti) builds.
893657fb
 
60b9d7ba
 ### Docker Builds
893657fb
 
60b9d7ba
 OpenShift supports Docker builds. Using this strategy, users may supply a URL to a Docker context which is used as the basis for a [Docker build](https://docs.docker.com/reference/commandline/cli/#build).
893657fb
 
60b9d7ba
 #### How It Works
893657fb
 
60b9d7ba
 To implement Docker builds, OpenShift provides build containers access to a node’s Docker daemon.
893657fb
 
60b9d7ba
 During a build, a pod containing a single container–a build container–is created. The node’s Docker socket is bind mounted into the build container. The build container executes `docker build` using the the supplied Docker context, and all interaction with Docker occurs via the node's Docker daemon.
893657fb
 
60b9d7ba
 **Advantages**
893657fb
 
60b9d7ba
 1.  Allows Docker builds in unprivileged containers
 2.  Minimizes image storage requirements
 3.  Reduces the number of Docker daemons required
893657fb
 
60b9d7ba
 **Disadvantages**
893657fb
 
60b9d7ba
 1.  Constraining resources per-user is made more difficult
 2.  Containers created during the build are created outside the scope of the kubelet
 3.  Container processes created during the build are children of a remote Docker process, making container cleanup more difficult
893657fb
 
60b9d7ba
 There are viable paths to alleviate or resolve each of these disadvantages, and this mechanism is considered a work in progress.
893657fb
 
60b9d7ba
 ##### Why not Docker-in-Docker?
893657fb
 
60b9d7ba
 It's theoretically possible to implement builds using a nested Docker daemon within a Docker container (Docker-in-Docker). On the surface, this approach offers some compelling advantages:
893657fb
 
60b9d7ba
 1.  Build process resources can be naturally constrained to the user’s acceptable limits (cgroups)
 2.  Containers created during the build have the build container as their parent process, making container cleanup simple
893657fb
 
60b9d7ba
 In practice, however, there are (at present) some serious problems with the approach which render it unusable:
893657fb
 
60b9d7ba
 1.  Requires a privileged container, which is a show-stopping security concern with no solution on the horizon
     * In addition, this nullifies the theoretical benefit of cgroups isolation, as the process could break out the container
 2.  With devicemapper, it's very easy to leak both loopback devices and storage on the host
b6c660ef
 3.  No easy way to share storage of images/layers among build containers, requiring each Docker-in-Docker instance to store its own unique, full copy of any image(s) downloaded during the build process.
60b9d7ba
     * A caching proxy running on the node could at least minimize the number of times an image is pulled from a remote registry, but that doesn’t eliminate the need for each build container to have its own copy of the images.
893657fb
 
60b9d7ba
 For these reasons, Docker-in-Docker is not considered a viable build strategy for a secure, multi-tenant production environment.
893657fb
 
f21c4a6b
 ### S2I (Source-to-Image) Builds
893657fb
 
f21c4a6b
 OpenShift also supports [Source-To-Images (s2i)](https://github.com/openshift/source-to-image#source-to-image-sti) builds.
893657fb
 
f21c4a6b
 Source-to-images (s2i) 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 which incorporates the base image and built source, and is ready to use with `docker run`. S2I supports incremental builds which re-use previously downloaded dependencies, previously built artifacts, etc.
06531c4f
 
 ### Custom Builds
 
 The custom build strategy is very similar to *Docker build* strategy, but users might
026414df
 customize the builder image that will be used for build execution. The *Docker build* uses [openshift/origin-docker-builder](https://hub.docker.com/r/openshift/origin-docker-builder/) image by default. Using your own builder image allows you to customize your build process.
06531c4f
 
 An example JSON of a custom build strategy:
 
 ```json
 "strategy": {
   "type": "Custom",
     "customStrategy": {
5fc5f61b
       "image": "my-custom-builder-image",
06531c4f
       "exposeDockerSocket": true,
       "env": [
         { "name": "EXPOSE_PORT", "value": "8080" }
       ]
     }
 }
 ```
 
 The `exposeDockerSocket` option will mount the Docker socket from host into your
 builder container and allows you to execute the `docker build` and `docker push` commands.
 Note that this might be restricted by the administrator in future.
 
 The `env` option allows you to specify additional environment variables that will
 be passed to the builder container environment. By default, these environment
 variables are passed to the build container:
 
 * `$BUILD` contains the JSON representation of the Build
 * `$OUTPUT_IMAGE` contains the output Docker image name as configured in Build
 * `$OUTPUT_REGISTRY` contains the output Docker registry as configured in Build
 * `$SOURCE_URI` contains the URL to the source code repository
 * `$SOURCE_REF` contains the branch, tag or ref for source repository
 * `$DOCKER_SOCKET` contains full path to the Docker socket