From 3bf46401db8d6ecbc79c3a394d8dca4c4521ee5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20Mass=C3=A9?= Date: Wed, 1 Aug 2018 14:57:46 +0200 Subject: [PATCH] using docker builds --- Docker-Builds/README.md | 454 +++++++++++++++++++++++++ Docker-Builds/custom-base/Dockerfile | 7 + Docker-Builds/custom-tomcat/Dockerfile | 43 +++ Docker-Builds/target-app/Dockerfile | 12 + 4 files changed, 516 insertions(+) create mode 100644 Docker-Builds/README.md create mode 100644 Docker-Builds/custom-base/Dockerfile create mode 100644 Docker-Builds/custom-tomcat/Dockerfile create mode 100644 Docker-Builds/target-app/Dockerfile diff --git a/Docker-Builds/README.md b/Docker-Builds/README.md new file mode 100644 index 0000000..c3ff89a --- /dev/null +++ b/Docker-Builds/README.md @@ -0,0 +1,454 @@ +# Using Docker Builds + +## Context + +Docker builds are the basis of the basis of every image construction in +OpenShift. Even if there are other build types (S2I, Fabric8, Custom, etc.), +Docker builds are the easiest and the most ubiquitous build type. + +Possible usages of the Docker build encompasses: + +- Creating or modifying a base image +- Creating an image of an application + +To use Docker builds, you will need two [Image Streams](https://docs.openshift.com/container-platform/latest/dev_guide/managing_images.html): + +- a source or input Image Stream +- a target or output Image Stream + +The [Image Stream](https://docs.openshift.com/container-platform/latest/dev_guide/managing_images.html) +is an indirection level that let you manage your images in a very flexible +way. An Image Stream contains tags and each tag can be: + +- a reference to an external image such as `docker.io/centos:7` or + `registry.access.redhat.com/rhel7:7.5`. +- a reference to another tag in the same image stream +- a reference to a tag in another image stream +- a container image by itself + +In addition to the Image Streams, we will also need a `Dockerfile`. + +## Practical example + +In this guide, we will take a real world scenario and implement it. In this +scenario, we would like to: + +- take the base image provided by Red Hat and add customizations to it +- take this new base image and create a middleware image that includes Tomcat +- take this middleware image and install a Tomcat application on it + +## Creating the source Image Stream + +For this example, we will use a CentOS or RHEL base image as a basis for our +subsequent builds. + +First, we will create a new project: + +```sh +oc new-project docker-builds +``` + +Import the RHEL 7.5 images in an image stream named `rh-base`: + +```sh +oc import-image rh-base:7.5 --from=registry.access.redhat.com/rhel7:7.5 --scheduled --confirm +``` + +Alternativelly, if you run on OpenShift Origin you can import the CentOS 7.5 images instead: + +```sh +oc import-image rh-base:7.5 --from=docker.io/centos:7.5.1804 --scheduled --confirm +``` + +**Note:** Although, there is a `--all` flag to the `oc import-image` command +that can mirror the tags from the remote registry to the image stream, it has +shortcomings and I would not recommend using it. Namely, it will not import +all tags but just the first five. This behavior is configurable, see the +[maxImagesBulkImportedPerRepository](https://docs.openshift.com/container-platform/3.9/install_config/master_node_configuration.html#master-config-image-policy-config) +parameter. Unless you really need to import a large number of tags, I would +suggest importing them explicitely. + +## Creating the target Image Stream + +In this example, we will create two target image streams: one for the corporate +image we will build and one for the application we will build. + +Create the `custom-base` image stream: + +```sh +oc create imagestream custom-base +``` + +Then, the `custom-tomcat` image stream: + +```sh +oc create imagestream custom-tomcat +``` + +And the `target-app` image stream: + +```sh +oc create imagestream target-app +``` + +## Create the first Docker build that builds the corporate base image + +Review the [Dockerfile](custom-base/Dockerfile) of our corporate base image and try to +build it locally: + +```sh +docker build -t custom-base:dev ./custom-base +``` + +You can then run this new image locally and play around with it: + +```raw +$ docker run -it custom-base:dev /bin/bash +[root@2329458e5159 /]# cat /etc/redhat-release +CentOS Linux release 7.5.1804 (Core) +[root@2329458e5159 /]# rsync --version +rsync version 3.1.2 protocol version 31 +Copyright (C) 1996-2015 by Andrew Tridgell, Wayne Davison, and others. +Web site: http://rsync.samba.org/ +Capabilities: + 64-bit files, 64-bit inums, 64-bit timestamps, 64-bit long ints, + socketpairs, hardlinks, symlinks, IPv6, batchfiles, inplace, + append, ACLs, xattrs, iconv, symtimes, prealloc + +rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you +are welcome to redistribute it under certain conditions. See the GNU +General Public Licence for details. +``` + +Once everything is fine, you can create the Docker build in OpenShift: + +```sh +oc new-build -D - --name=custom-base --image-stream=rh-base:7.5 --to=custom-base:7.5 < custom-base/Dockerfile +``` + +OpenShift has created the build config and started a new build. Follow the +build progression with: + +```sh +oc logs -f bc/custom-base +``` + +Did you notice at the very beginning of the build log how OpenShift replaced +the `FROM centos:latest` with the correct image stream reference ? + +```raw +Step 1/4 : FROM registry.access.redhat.com/rhel7@sha256:135cbbec4581cd8b2f550dd90dea06affb55def73c7421e64091dc3f638d05e4 +``` + +Now, create a dummy container based on this new image: + +```sh +oc new-app --name custom-base --image-stream=custom-base:7.5 +oc patch dc custom-base --type=json -p '[{"op": "add", "path": "/spec/template/spec/containers/0/command", "value": ["/bin/sh", "-c", "while :; do sleep 1; done" ]}]' +``` + +Watch the container being created: + +```sh +oc get pods -w -l app=custom-base +``` + +Once created, get a shell and play around with it: + +```raw +$ oc rsh $(oc get pods -l app=custom-base -o name|tail -n 1) +sh-4.2$ cat /etc/redhat-release +Red Hat Enterprise Linux Server release 7.5 (Maipo) +sh-4.2$ rsync --version +rsync version 3.1.2 protocol version 31 +Copyright (C) 1996-2015 by Andrew Tridgell, Wayne Davison, and others. +Web site: http://rsync.samba.org/ +Capabilities: + 64-bit files, 64-bit inums, 64-bit timestamps, 64-bit long ints, + socketpairs, hardlinks, symlinks, IPv6, batchfiles, inplace, + append, ACLs, xattrs, iconv, symtimes, prealloc + +rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you +are welcome to redistribute it under certain conditions. See the GNU +General Public Licence for details. +``` + +Although everything went smoothly, there is a catch in this setup: the +[Docker layer cache](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#leverage-build-cache). +If you run this build several times, you can see that subsequent builds +are much faster. + +```raw +$ oc get builds +NAME TYPE FROM STATUS STARTED DURATION +custom-base-1 Docker Dockerfile Complete 1 hours ago 3m53s +custom-base-2 Docker Dockerfile Complete 3 minutes ago 6s +``` + +This might seems a good point but if a new security patch is released for +the `rsync` package we installed, it cannot be installed by triggering a new +build. + +There is a settings to enable to prevent this behavior: + +```sh +oc patch bc custom-base -p '{ "spec": { "strategy": { "dockerStrategy": { "noCache": true } } } }' +``` + +You can trigger a new build and check that the layer cache is not used anymore: + +```sh +oc start-build custom-base +``` + +The new build does not use the layer caching mechanism: + +```raw +$ oc get builds +NAME TYPE FROM STATUS STARTED DURATION +custom-base-1 Docker Dockerfile Complete 1 hours ago 3m53s +custom-base-2 Docker Dockerfile Complete 15 minutes ago 6s +custom-base-3 Docker Dockerfile Complete 4 minutes ago 3m37s +``` + +## Create the second Docker build that builds the middleware image + +In this example, we will build an image containing [tomcat](https://tomcat.apache.org/). + +Start by reviewing the [Dockerfile](custom-tomcat/Dockerfile) of our middleware +image and try to build it locally: + +```sh +docker build -t custom-tomcat:dev ./custom-tomcat --build-arg TOMCAT_URL=https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.8/bin/apache-tomcat-9.0.8.tar.gz +``` + +You can then run this new image locally: + +```sh +docker run --name tomcat -d -p 8080:8080 custom-tomcat:dev run +docker logs -f tomcat +``` + +And make sure tomcat is working properly: + +```raw +$ curl -s http://localhost:8080/ |head -n 20 + + + + + + + + Apache Tomcat/9.0.8 + + + + + + +
+