#**Lab 2: Creating and Application using a Dockerfile**
In this exercise we will learn how to create an application from a Dockerfile.
OpenShift takes Dockerfile as an input and generates your application docker image for you.
**Step 1: Create a project or use an existing project**
If you want to, you can create a new project based on what you have learnt in the previous lab.
Since we already have a project we will use it. Run the following command to make sure.
**Remember** to substitute UserName with your username.
$ oc project mycliproject-username
**Step 2: 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 php project on github
https://github.com/eformat/time/tree/master/sh
Note: there is also a php version of this under the php folder.
Look at the Dockerfile for this project. It starts off with a [busybox](http://www.busybox.net/) image.
It copies the source code which is a simple one line bash script and exposes port 8080.
Look at the src folder, you will find a simple `init.sh` file that just displays the current datetime.
**Docker Build**: 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 in 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 and correct source directory `sh` as the parameters.
$ oc new-app https://github.com/eformat/time.git --context-dir=sh
--> Found Docker image eb3c0d4 (3 weeks old) from docker.io for "docker.io/busybox"
* An image stream will be created as "busybox:latest" that will track this image
* A Docker build using source code from https://github.com/eformat/time.git will be created
* The resulting image will be pushed to image stream "time:latest"
* Every time "busybox: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"
--> Creating resources with label app=time ...
ImageStream "busybox" created
ImageStream "time" created
BuildConfig "time" created
DeploymentConfig "time" created
Service "time" created
--> Success
Build scheduled for "time" - use the logs command to track its progress.
Run 'oc status' to view your app.
A build was created and scheduled - you can also run `oc start-build time` to start another build manually.
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.
**Step 3: Build**
In the meanwhile lets have a look at the buildconfig by running the command shown below.
$ oc get bc -o json
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "BuildConfig",
"apiVersion": "v1",
"metadata": {
"name": "time",
"namespace": "mycliproject-username",
"selfLink": "/oapi/v1/namespaces/mycliproject-username/buildconfigs/time",
"uid": "5a7301eb-921f-11e5-b8e4-525400b36d1d",
"resourceVersion": "34243",
"creationTimestamp": "2015-11-23T20:18:26Z",
"labels": {
"app": "time"
},
"annotations": {
"openshift.io/generated-by": "OpenShiftNewApp"
}
},
"spec": {
"triggers": [
{
"type": "GitHub",
"github": {
"secret": "r0QnSn28As_fPaFgZcwV"
}
},
{
"type": "Generic",
"generic": {
"secret": "Z6zH_y8CCB98FIBBgcKT"
}
},
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChange": {
"lastTriggeredImageID": "docker.io/library/busybox@sha256:eb3c0d4680f9213ee5f348ea6d39489a1f85a318a2ae09e012c426f78252a6d2"
}
}
],
"source": {
"type": "Git",
"git": {
"uri": "https://github.com/eformat/time.git"
},
"contextDir": "sh"
},
"strategy": {
"type": "Docker",
"dockerStrategy": {
"from": {
"kind": "ImageStreamTag",
"name": "busybox:latest"
}
}
},
"output": {
"to": {
"kind": "ImageStreamTag",
"name": "time:latest"
}
},
"resources": {}
},
"status": {
"lastVersion": 1
}
}
]
}
Note the name of the buildconfig in metadata is set to "time", the git uri pointing to the value you gave while creating the application.
Also note the Strategy.type set to "Docker". This indicates that the build will use the instructions in this Dockerfile to do the docker build.
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 of the buildconfig.
$ oc get builds
NAME TYPE STATUS POD
time-1 Docker Running time-1-build
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
....
....
Successfully built 544f76e7729c
I1118 01:16:36.935789 1 docker.go:86] Pushing image 172.30.234.236:5000//time:latest ...
I1118 01:17:06.434614 1 docker.go:90] Push successful
In the above log note how the image is pushed to the local docker registry. In this example - the registry is running at 172.30.234.236 at port 5000, you
should see a similar address range.
**Step 4: 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 dc -o json
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "time",
"namespace": "mycliproject-username",
"selfLink": "/oapi/v1/namespaces/mycliproject-username/deploymentconfigs/time",
"uid": "5a76629b-921f-11e5-b8e4-525400b36d1d",
"resourceVersion": "34284",
"creationTimestamp": "2015-11-23T20:18:26Z",
"labels": {
"app": "time"
},
"annotations": {
"openshift.io/generated-by": "OpenShiftNewApp"
}
},
"spec": {
"strategy": {
"type": "Rolling",
"rollingParams": {
"updatePeriodSeconds": 1,
"intervalSeconds": 1,
"timeoutSeconds": 600,
"maxUnavailable": "25%",
"maxSurge": "25%"
},
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"time"
],
"from": {
"kind": "ImageStreamTag",
"name": "time:latest"
},
"lastTriggeredImage": "172.30.183.116:5000/mycliproject-username/time@sha256:ebf2150a3d927f56654db955b40af8bac9ac496da0cb10c694ff1310acf4de2d"
}
}
],
"replicas": 1,
"selector": {
"app": "time",
"deploymentconfig": "time"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"app": "time",
"deploymentconfig": "time"
},
"annotations": {
"openshift.io/generated-by": "OpenShiftNewApp"
}
},
"spec": {
"containers": [
{
"name": "time",
"image": "172.30.183.116:5000/mycliproject-username/time@sha256:ebf2150a3d927f56654db955b40af8bac9ac496da0cb10c694ff1310acf4de2d",
"ports": [
{
"containerPort": 8080,
"protocol": "TCP"
}
],
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"imagePullPolicy": "Always"
}
],
"restartPolicy": "Always",
"terminationGracePeriodSeconds": 30,
"dnsPolicy": "ClusterFirst",
"securityContext": {}
}
}
},
"status": {
"latestVersion": 1,
"details": {
"causes": [
{
"type": "ImageChange",
"imageTrigger": {
"from": {
"kind": "DockerImage",
"name": "172.30.183.116:5000/mycliproject-username/time:latest"
}
}
}
]
}
}
}
]
}
Note where the image is picked from. It shows that the deployment picks the image from the local registry (the same ipaddress
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 REASON RESTARTS AGE
time-1-build 0/1 ExitCode:0 0 9m
time-2-who1k 1/1 Running 0 43s
**Step 5: 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 services
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
time 172.30.***.*** 8080/TCP app=time,deploymentconfig=time 3m
**Replace with your username here** You can use `services` or the shortcut `svc` interchangeably. This is the same for most objects e.g. `is` for `imagestreams` etc.
$ oc expose svc time
NAME HOST/PORT PATH SERVICE LABELS TLS TERMINATION
time time app=time
$ oc get routes
NAME HOST/PORT PATH SERVICE LABELS TLS TERMINATION
time time-mycliproject-username.apps.osecloud.com time app=time
**Note:** Unlike in the previous lab, this time I did not use `--hostname` parameter while exposing the service to create a route.
OpenShift by default automatically assigned the project name extension to the route name.
**Step 6: 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-mycliproject-username.apps.osecloud.com
Wed Nov 18 07:19:34 UTC 2015
**Congratulations!!** In this exercise you have learnt how to create, build and deploy an application using OpenShift's "Docker Build strategy".