Create an App using Docker build

In this recipe you will learn how to create an application from a Dockerfile. OpenShift takes Dockerfile as an input and generates your application docker image for you.

Create a project or use an existing project

If you want to, you can create a new project based on what you have learned in the previous lab. Since we already have a project we will use it. Run the following command to make sure.

$ oc project ocp-test

Create an application that uses docker file

This time we will use a project that has a Dockerfile in a source code repository. We will use a simple project on github (https://github.com/jbosschina/time). "rhel" folder from this github project is built starting with rhel7 as the base image which is described in Dockerfile.

Look at the Dockerfile for this project. It starts off with registry.access.redhat.com/rhel7 image. It copies the source code which is a simple init.sh file and exposes port 8080. Look at the init.sh that just displays the current datetime. There is also a PHP version of the same project available in the php folder if you like to use that. The php version does exactly the same it has a time.php file that displays the time.

When OpenShift finds a Dockerfile in the source, it uses this Dockerfile as the basis to create a docker image for your application. This strategy is called Docker Build strategy on OpenShift. We’ll see more about it when we look at the build configuration a couple of steps down the line. Once OpenShift builds the application’s docker image, it stores that in a local docker registry. Later it uses this image to deploy an application that runs in a pod.

Now let’s create an application using this approach. We will run oc new-app command by supplying the git uri as the parameter.

$ oc new-app https://github.com/jbosschina/time --context-dir=rhel
--> Found Docker image bdcfb1a (2 weeks old) from registry.access.redhat.com for "registry.access.redhat.com/rhel7"

    Red Hat Enterprise Linux 7
    --------------------------
    Tags: base rhel7

    * An image stream will be created as "rhel7:latest" that will track the source image
    * A Docker build using source code from https://github.com/jbosschina/time will be created
      * The resulting image will be pushed to image stream "time:latest"
      * Every time "rhel7:latest" changes a new build will be triggered
    * This image will be deployed in deployment config "time"
    * Port 8080 will be load balanced by service "time"
      * Other containers can access this service through the hostname "time"
    * WARNING: Image "registry.access.redhat.com/rhel7" runs as the 'root' user which may not be permitted by your cluster administrator

--> Creating resources ...
    imagestream "rhel7" created
    imagestream "time" created
    buildconfig "time" created
    deploymentconfig "time" created
    service "time" created
--> Success
    Build scheduled, use 'oc logs -f bc/time' to track its progress.
    Run 'oc status' to view your app.

You’ll notice that OpenShift created a few things at this point. You will find a buildconfig, deploymentconfig, service and imagestreams in the above list. The application is not running yet. It needs to be built and deployed. Within a minute or so, you will see that OpenShift starts the build.

Build

In the meanwhile lets have a look at the buildconfig by running the command shown below.

$ oc get buildconfig time -o json
{
    "apiVersion": "v1",
    "kind": "BuildConfig",
    "metadata": {
        "annotations": {
            "openshift.io/generated-by": "OpenShiftNewApp"
        },
        "creationTimestamp": "2017-07-09T13:16:22Z",
        "labels": {
            "app": "time"
        },
        "name": "time",
        "namespace": "ocp-test",
        "resourceVersion": "4617226",
        "selfLink": "/oapi/v1/namespaces/ocp-test/buildconfigs/time",
        "uid": "cdd4215f-64a8-11e7-bbc1-0682973451aa"
    },
    "spec": {
        "nodeSelector": null,
        "output": {
            "to": {
                "kind": "ImageStreamTag",
                "name": "time:latest"
            }
        },
        "postCommit": {},
        "resources": {},
        "runPolicy": "Serial",
        "source": {
            "contextDir": "rhel",
            "git": {
                "uri": "https://github.com/jbosschina/time"
            },
            "type": "Git"
        },
        "strategy": {
            "dockerStrategy": {
                "from": {
                    "kind": "ImageStreamTag",
                    "name": "rhel7:latest"
                }
            },
            "type": "Docker"
        },
        "triggers": [
            {
                "github": {
                    "secret": "hhoRslLTEI4XqXUEKzXa"
                },
                "type": "GitHub"
            },
            {
                "generic": {
                    "secret": "zFoI6AgPoYzqsdzIjLRY"
                },
                "type": "Generic"
            },
            {
                "type": "ConfigChange"
            },
            {
                "imageChange": {
                    "lastTriggeredImageID": "registry.access.redhat.com/rhel7@sha256:582cb940a6e730dbdffee7cc5e1983522fdeeb3c40bea7373b255a209124cc02"
                },
                "type": "ImageChange"
            }
        ]
    },
    "status": {
        "lastVersion": 1
    }
}

Build starts in a minute or so. You can view the list of builds using oc get builds command. You can also start the build using oc start-build time where time is the name we noticed in the buildconfig.

$ oc get builds
NAME      TYPE      FROM          STATUS     STARTED         DURATION
time-1    Docker    Git@39a16e6   Complete   6 minutes ago   27s

Note the name of the build that is running i.e. time-1. We will use that name to look at the build logs. Run the command as shown below to look at the build logs. This will run for a few mins. At the end you will notice that the docker image is successfully created and it will start pushing this to OpenShift’s internal docker registry.

$ oc logs build/time-1
Cloning "https://github.com/jbosschina/time" ...
	Commit:	39a16e6b59ad96b0a15714e54d6eaebbaa1fb164 (Update init.sh)
	Author:	VeerMuchandi <veer.muchandi@gmail.com>
	Date:	Wed Sep 14 20:45:02 2016 -0400
Step 1 : FROM registry.access.redhat.com/rhel7@sha256:582cb940a6e730dbdffee7cc5e1983522fdeeb3c40bea7373b255a209124cc02
 ---> 93bb76ddeb7a
Step 2 : MAINTAINER Veer Muchandi veer@redhat.com
 ---> Using cache
 ---> 2dc7bfa96e21
Step 3 : ADD ./init.sh ./
 ---> Using cache
 ---> d8ade3d469e4
Step 4 : RUN yum install nmap-ncat --disablerepo=* --enablerepo=rhel-7-server-rpms -y && yum clean all -y
 ---> Using cache
 ---> 8086a11d8fe1
Step 5 : RUN chown 1001:1001 init.sh && chmod o+w init.sh
 ---> Using cache
 ---> 30a080a82f28
Step 6 : USER 1001
 ---> Using cache
 ---> 0c2fd2cf75b5
Step 7 : EXPOSE 8080
 ---> Using cache
 ---> 69fa2a904898
Step 8 : CMD ./init.sh
 ---> Using cache
 ---> 0c157fd9c41f
Step 9 : ENV "OPENSHIFT_BUILD_NAME" "time-1" "OPENSHIFT_BUILD_NAMESPACE" "ocp-test" "OPENSHIFT_BUILD_SOURCE" "https://github.com/jbosschina/time" "OPENSHIFT_BUILD_COMMIT" "39a16e6b59ad96b0a15714e54d6eaebbaa1fb164"
 ---> Running in 8348cc695f40
 ---> cfdc5623eb2d
Removing intermediate container 8348cc695f40
Step 10 : LABEL "io.openshift.build.commit.author" "VeerMuchandi \u003cveer.muchandi@gmail.com\u003e" "io.openshift.build.commit.date" "Wed Sep 14 20:45:02 2016 -0400" "io.openshift.build.commit.id" "39a16e6b59ad96b0a15714e54d6eaebbaa1fb164" "io.openshift.build.commit.ref" "master" "io.openshift.build.commit.message" "Update init.sh" "io.openshift.build.source-location" "https://github.com/jbosschina/time" "io.openshift.build.source-context-dir" "rhel"
 ---> Running in 071fe3f76a40
 ---> c14de1c75ecf
Removing intermediate container 071fe3f76a40
Successfully built c14de1c75ecf
Pushing image 172.30.160.227:5000/ocp-test/time:latest ...
Pushed 0/5 layers, 2% complete
Pushed 1/5 layers, 28% complete
Pushed 2/5 layers, 46% complete
Pushed 3/5 layers, 64% complete
Pushed 4/5 layers, 81% complete
Pushed 5/5 layers, 100% complete
Push successful

In the above log note how the image is pushed to the local docker registry. The registry is running at 172.30.160.227 at port 5000.

Deployment

Once the image is pushed to the docker registry, OpenShift will trigger a deploy process. Let us also quickly look at the deployment configuration by running the following command. Note dc represents deploymentconfig.

$ oc get deploymentconfig time -o json
{
    "apiVersion": "v1",
    "kind": "DeploymentConfig",
    "metadata": {
        "annotations": {
            "openshift.io/generated-by": "OpenShiftNewApp"
        },
        "creationTimestamp": "2017-07-09T13:16:23Z",
        "generation": 2,
        "labels": {
            "app": "time"
        },
        "name": "time",
        "namespace": "ocp-test",
        "resourceVersion": "4617319",
        "selfLink": "/oapi/v1/namespaces/ocp-test/deploymentconfigs/time",
        "uid": "cdf17ba6-64a8-11e7-bbc1-0682973451aa"
    },
    "spec": {
        "replicas": 1,
        "selector": {
            "app": "time",
            "deploymentconfig": "time"
        },
        "strategy": {
            "activeDeadlineSeconds": 21600,
            "resources": {},
            "rollingParams": {
                "intervalSeconds": 1,
                "maxSurge": "25%",
                "maxUnavailable": "25%",
                "timeoutSeconds": 600,
                "updatePeriodSeconds": 1
            },
            "type": "Rolling"
        },
        "template": {
            "metadata": {
                "annotations": {
                    "openshift.io/generated-by": "OpenShiftNewApp"
                },
                "creationTimestamp": null,
                "labels": {
                    "app": "time",
                    "deploymentconfig": "time"
                }
            },
            "spec": {
                "containers": [
                    {
                        "image": "172.30.160.227:5000/ocp-test/time@sha256:15406997a5964509c34525194c416996f9704d237f860c88c5330993c96a1d12",
                        "imagePullPolicy": "Always",
                        "name": "time",
                        "ports": [
                            {
                                "containerPort": 8080,
                                "protocol": "TCP"
                            }
                        ],
                        "resources": {},
                        "terminationMessagePath": "/dev/termination-log"
                    }
                ],
                "dnsPolicy": "ClusterFirst",
                "restartPolicy": "Always",
                "securityContext": {},
                "terminationGracePeriodSeconds": 30
            }
        },
        "test": false,
        "triggers": [
            {
                "type": "ConfigChange"
            },
            {
                "imageChangeParams": {
                    "automatic": true,
                    "containerNames": [
                        "time"
                    ],
                    "from": {
                        "kind": "ImageStreamTag",
                        "name": "time:latest",
                        "namespace": "ocp-test"
                    },
                    "lastTriggeredImage": "172.30.160.227:5000/ocp-test/time@sha256:15406997a5964509c34525194c416996f9704d237f860c88c5330993c96a1d12"
                },
                "type": "ImageChange"
            }
        ]
    },
    "status": {
        "availableReplicas": 1,
        "conditions": [
            {
                "lastTransitionTime": "2017-07-09T13:16:59Z",
                "lastUpdateTime": "2017-07-09T13:16:59Z",
                "message": "Deployment config has minimum availability.",
                "status": "True",
                "type": "Available"
            },
            {
                "lastTransitionTime": "2017-07-09T13:16:55Z",
                "lastUpdateTime": "2017-07-09T13:17:00Z",
                "message": "replication controller \"time-1\" successfully rolled out",
                "reason": "NewReplicationControllerAvailable",
                "status": "True",
                "type": "Progressing"
            }
        ],
        "details": {
            "causes": [
                {
                    "imageTrigger": {
                        "from": {
                            "kind": "ImageStreamTag",
                            "name": "time:latest",
                            "namespace": "ocp-test"
                        }
                    },
                    "type": "ImageChange"
                }
            ],
            "message": "image change"
        },
        "latestVersion": 1,
        "observedGeneration": 2,
        "readyReplicas": 1,
        "replicas": 1,
        "unavailableReplicas": 0,
        "updatedReplicas": 1
    }
}

Note where the image is picked from. It shows that the deployment picks the image from the local registry (same ip address and port as in buildconfig) and the image tag is same as what we built earlier. This means the deployment step deploys the application image what was built earlier during the build step.

If you get the list of pods, you’ll notice that the application gets deployed quickly and starts running in its own pod.

$ oc get pods
NAME           READY     STATUS      RESTARTS   AGE
time-1-build   0/1       Completed   0          12m
time-1-sj1wz   1/1       Running     0          11m

Adding route

This step is very much the same as what we did in the previous exercise. We will check the service and add a route to expose that service.

$ oc get service
NAME      CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
time      172.30.85.105   <none>        8080/TCP   14m

Here we expose the service as a route.

$ oc expose service time
route "time" exposed

And then we check the route exposed.

$ oc get routes
NAME      HOST/PORT                                      PATH      SERVICES   PORT       TERMINATION   WILDCARD
time      time-ocp-test.apps.example.com             time       8080-tcp                 None

Run the application

Now run the application by using the route you provided in the previous step. You can use either curl or your browser. The application displays time.

$ curl time-ocp-test.apps.example.com
Sun Jul  9 13:16:58 UTC 2017
Host: time-1-sj1wz

Congratulations!! In this exercise you have learnt how to create, build and deploy an application using OpenShift’s Docker Build strategy.

results matching ""

    No results matching ""