4 Ways to do a Dockerfile Build in OpenShift

In OpenShift, you can build a Docker image inside your cluster, and push it to OpenShift’s own internal image registry. Learning how to build an image from a Dockerfile is a very common stage in the journey of how to deploy your own apps on OpenShift.

Dockerfile based builds are also useful when you want to deploy an application into OpenShift, but you can’t pull it from another registry.

Build it yourself

So, you want to build an image yourself in the cluster, perhaps either using Source-to-Image, or with a Dockerfile.

Dockerfiles are pretty common, so in this article we’re going to look at some common variations on building an image in OpenShift using a Docker build, with build instructions located nicely in a Dockerfile. Nice.

TODO about Docker builds

Docker builds in OpenShift

Building an image from a Dockerfile is not as hard as you think

Docker builds in OpenShift by Tutorial Works is licensed under CC BY-SA 4.0

It starts with a BuildConfig

If you haven’t taken OpenShift 101, then a BuildConfig

4 BuildConfig examples

Now you’ve learned the basics of builds, let’s take a look at some examples.

To apply each of these examples to an OpenShift cluster, you can use the oc apply command.

1. Basic OpenShift Docker BuildConfig example (from Git)

Keeping your Dockerfile in a Git repository is a great option.

Dockerfile in your Git repository

It’s easier to manage everything when you keep your build scripts in the same repository as your code.

Plus, you also get the advantage of being able to version-control your Dockerfile, just like your application’s code.

To use a Dockerfile from a Git repository, you need to specify strategy.type as Docker, and then use the dockerStrategy.dockerfilePath field to give the path to your Dockerfile.

Here’s an example:

apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  name: mywebsite
  labels:
    app: mywebsite
spec:
  source:
    type: Git
    git:
      uri: https://github.com/monodot/container-up
    contextDir: httpd-hello-world
  strategy:
    type: Docker                      
    dockerStrategy:
      dockerfilePath: Dockerfile    # Look for Dockerfile in: gitUri/contextDir/dockerfilePath
  output:
    to:
      kind: ImageStreamTag
      name: mywebsite:latest

2. Use an image stream as a base image

I like image streams, they’re a nice feature of OpenShift. They allow you to create a local “pointer” to a set of image tags.

When you use an image stream, you don’t need to hardcode the full registry URL everywhere, including your BuildConfig.

OpenShift will resolve the image and use it as the from image in your Docker build.

Use image stream as a FROM image

When you use an image stream in a BuildConfig, you can also set an image change event as a trigger – for example, to trigger a new build when a new image is pushed to a tag.

First, let’s set up an image stream to use as an example.

I create a local imagestream called httpd, which points to Bitnami’s Apache image on Docker Hub. Here’s an example ImageStream YAML definition for that:

apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
  name: httpd
spec:
  lookupPolicy:
    local: false
  tags:
  - name: latest
    from:
      kind: DockerImage
      name: bitnami/apache
    referencePolicy:
      type: Source

Next, create the BuildConfig, to perform a Docker build in OpenShift.

The image stream details go in the .spec.strategy.dockerStrategy.from section, like this example:

apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  name: mywebsite
  labels:
    app: mywebsite
spec:
  source:
    type: Git
    git:
      uri: https://github.com/monodot/container-up
    contextDir: httpd-hello-world
  strategy:
    type: Docker                      
    dockerStrategy:
      dockerfilePath: Dockerfile
      from:
        kind: ImageStreamTag       # Use an imagestream tag as 'FROM'
        namespace: toms-project    # Which project?
        name: httpd:latest         # Use the imagestream created above
  output:
    to:
      kind: ImageStreamTag
      name: mywebsite:latest
  triggers:
  - type: ImageChange              # Trigger a build on image change

Now, when the build runs, OpenShift will replace the FROM line in your Dockerfile with the image from the image stream.

In the logs, you can see OpenShift replacing the FROM instruction:

Screenshot from oc start-build with an imagestream

OpenShift will replace the FROM line whe you use an imagestream in a build

3. Dockerfile inside the BuildConfig itself

The final option I want to show you is writing a Dockerfile inside the BuildConfig itself. This is called an inline Dockerfile.

Explicit Dockerfile in a BuildConfig

You can include a complete Dockerfile inside the BuildConfig object.

When this approach is combined with spec.source.type=Git, OpenShift will check out code from your Git repository, cd into the directory, then run a Docker build using your inline Dockerfile.

You can use a | pipe symbol in YAML to mark the start of a multiline string with line breaks, so you can write a complete Dockerfile.

Here’s the example:

apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  name: mywebsite
spec:
  source:
    type: Git
    git:
      uri: https://github.com/monodot/container-up   # clone this code
    contextDir: httpd-hello-world                    # cd to this directory
    dockerfile: |
      FROM bitnami/apache:latest
      COPY ./public_html/ /app
  strategy:
    type: Docker
  output:
    to:
      kind: ImageStreamTag
      name: mywebsite:latest

The syntax looks a little weird, but this trick allows you to create a custom Docker build, without needing to store the Dockerfile in a Git repository.

Next steps

Thanks for reading! I hope you found these example BuildConfigs useful.

Docker builds are an alternative to source-to-image (S2I) builds and you’ll probably find them useful when you’ve already written an app with a Dockerfile, and you simply want to move your app into OpenShift.

Once you’ve got the basics of Docker builds, you might want to add some 🌟 automation 🌟 and learn how to run a Docker build inside a Jenkins pipeline on OpenShift.

And then, once you’ve built your image, how about learning how to deploy it to Kubernetes, by looking at some Kubernetes Deployment examples?

Comments

Got any thoughts on what you've just read? Anything wrong, or no longer correct? Sign in with your GitHub account to leave a comment.

(All comments get added as Issues in our GitHub repo here, using the comments tool Utterances)