Custom S2I Template

Edit

When you are familiar with Source-to-Image (S2I), you can customize the builder image template (i.e. S2I/B2I template) based on your project to extend the S2I. There are some common-used built-in image builder templates including Python, Java, etc. KubeSphere 2.1.1 allows you to customize B2I template.

Before stepping into how to customize S2I builder image template, we introduce the required elements for a custom S2I template. It includes the following two parts in a custom S2I template:

  • Part 1: S2I custom builder image

    • assemble (required): The assemble script builds the application artifacts from a source and places them into appropriate directories inside the image.
    • run (required): The run script executes your application.
    • save-artifacts (optional): The save-artifacts script gathers all dependencies that can speed up the build processes that follow.
    • usage (optional): It allows you to inform the user how to properly use your image.
    • test: It allows you to create a simple process to check if the image is working correctly.
  • Part 2: the definition of S2Itemplate which describes the basic environment of building the application.

The builder image is compatible with OpenShift, which can be used in KubeSphere directly. For further information regarding S2I builder image, please see S2IRun.

In the following steps, we will demonstrate how to create a builder image that contains an Nginx service.

S2I also supports a different type of image template called runtime image or non-builder image. Please refer to https://github.com/kubesphere/s2irun/blob/master/docs/runtime_image.md for further information.

Step 1: Prepare S2I Builder Directory

S2I CLI is very convenient to bootstrap a new base directory of the image builder repository. Download the CLI and unpack it:

  1. $ wget https://github.com/openshift/source-to-image/releases/download/v1.1.14/source-to-image-v1.1.14-874754de-linux-386.tar.gz
  2. $ tar -xvf source-to-image-v1.1.14-874754de-linux-386.tar.gz
  3. $ ls
  4. s2i source-to-image-v1.1.14-874754de-linux-386.tar.gz sti
  5. $ cp s2i /usr/local/bin

In this guide we use nginx-centos7 as the name of the builder image. Create the initial base directory.

  1. s2i create nginx-centos7 s2i-builder-docs

The s2i create is responsible for bootstrapping a new S2I enabled image repository. This command will generate a skeleton .s2i directory and populate it with sample S2I scripts you can start hacking on. The directory tree lists as follows.

  1. s2i-builder-docs/
  2. Dockerfile - Defines the base builder image
  3. Makefile - Script for the builder image of testing and build
  4. test/
  5. run - Script that runs the application
  6. test-app/ - Test application source code
  7. s2i/bin
  8. assemble - Script that builds the application
  9. run - Script that runs the application
  10. usage - Script that prints the usage of the builder

Step 2: Modify the Dockerfile

A Dockerfile installs all of the necessary tools and libraries that are needed to build and run our application. This file will also handle copying the s2i scripts into the created image. Modify the Dockerfile to define the builder image as follows:

Dockerfile

  1. # nginx-centos7
  2. FROM kubespheredev/s2i-base-centos7:1
  3. # Here you can specify the maintainer for the image that you're building
  4. LABEL maintainer="Runze Xia <runzexia@yunify.com>"
  5. # Define the current version of the application
  6. ENV NGINX_VERSION=1.6.3
  7. # Set the labels that are used for KubeSphere to describe the builder image.
  8. LABEL io.k8s.description="Nginx Webserver" \
  9. io.k8s.display-name="Nginx 1.6.3" \
  10. io.kubesphere.expose-services="8080:http" \
  11. io.kubesphere.tags="builder,nginx,html"
  12. # Install the nginx web server package and clean the yum cache
  13. RUN yum install -y epel-release && \
  14. yum install -y --setopt=tsflags=nodocs nginx && \
  15. yum clean all
  16. # Change the default port for nginx
  17. RUN sed -i 's/80/8080/' /etc/nginx/nginx.conf
  18. RUN sed -i 's/user nginx;//' /etc/nginx/nginx.conf
  19. # Copy the S2I scripts to /usr/libexec/s2i since we set the label that way
  20. COPY ./s2i/bin/ /usr/libexec/s2i
  21. RUN chown -R 1001:1001 /usr/share/nginx
  22. RUN chown -R 1001:1001 /var/log/nginx
  23. RUN chown -R 1001:1001 /var/lib/nginx
  24. RUN touch /run/nginx.pid
  25. RUN chown -R 1001:1001 /run/nginx.pid
  26. RUN chown -R 1001:1001 /etc/nginx
  27. USER 1001
  28. # Set the default port for applications built using this image
  29. EXPOSE 8080
  30. # Modify the usage script in your application dir to inform the user how to run this image.
  31. CMD ["/usr/libexec/s2i/usage"]

S2I script uses the parameters from the labels defined in the Dockerfile. If you use the base image that is not provided by KubeSphere S2I, please refer to S2I Script.

Step 3: Create S2I Builder Scripts

assemble

Create an assemble script that builds our application. The script can also specify a way to restore any saved artifacts from the previous image. It just copies the configuration file and static contents to the target container.

  1. #!/bin/bash -e
  2. if [[ "$1" == "-h" ]]; then
  3. exec /usr/libexec/s2i/usage
  4. fi
  5. echo "---> Building and installing application from source..."
  6. if [ -f /tmp/src/nginx.conf ]; then
  7. mv /tmp/src/nginx.conf /etc/nginx/nginx.conf
  8. fi
  9. if [ "$(ls -A /tmp/src)" ]; then
  10. mv /tmp/src/* /usr/share/nginx/html/
  11. fi

s2i build places the source code in /tmp/src. We just copy the application source code to kubespheredev/s2i-base-centos7:1. It is also the working directory of kubespheredev/s2i-base-centos7:1.

run

Create a run script that starts the application.

  1. #!/bin/bash -e
  2. exec /usr/sbin/nginx -g "daemon off;"

We use exec command to execute the process of nginx web server. This command also allows all signals can be received by nginx sent from docker.

The save-artifacts script allows a new build to reuse content from a previous version of the application image. We can delete the save-artifacts script since we do not use it in this demo.

usage

Create a usage script that prints out instructions on how to use the image.

  1. #!/bin/bash -e
  2. cat <<EOF
  3. This is the nginx-centos7 S2I image:
  4. To use it, install S2I: https://github.com/kubesphere/s2i-operator
  5. Sample invocation:
  6. s2i build test/test-app kubespheredev/nginx-centos7 nginx-centos7-app
  7. You can then run the resulting image via:
  8. docker run -d -p 8080:8080 nginx-centos7-app
  9. and see the test via http://localhost:8080
  10. EOF

Step 4: Build and Run

Makefile

Modify the image name in makefile:

  1. IMAGE_NAME = kubespheredev/nginx-centos7-s2ibuilder-sample
  2. # Create a builder image named above based on the Dockerfile that was created previously.
  3. .PHONY: build
  4. build:
  5. docker build -t $(IMAGE_NAME) .
  6. # The builder image can be tested using the following commands:
  7. .PHONY: test
  8. test:
  9. docker build -t $(IMAGE_NAME)-candidate .
  10. IMAGE_NAME=$(IMAGE_NAME)-candidate test/run

Execute make build to create the builder image for nginx:

  1. $ make build
  2. docker build -t kubespheredev/nginx-centos7-s2ibuilder-sample .
  3. Sending build context to Docker daemon 164.9kB
  4. Step 1/17 : FROM kubespheredev/s2i-base-centos7:1
  5. ---> 48f8574c05df
  6. Step 2/17 : LABEL maintainer="Runze Xia <runzexia@yunify.com>"
  7. ---> Using cache
  8. ---> d60ebf231518
  9. Step 3/17 : ENV NGINX_VERSION=1.6.3
  10. ---> Using cache
  11. ---> 5bd34674d1eb
  12. Step 4/17 : LABEL io.k8s.description="Nginx Webserver" io.k8s.display-name="Nginx 1.6.3" io.kubesphere.expose-services="8080:http" io.kubesphere.tags="builder,nginx,html"
  13. ---> Using cache
  14. ---> c837ad649086
  15. Step 5/17 : RUN yum install -y epel-release && yum install -y --setopt=tsflags=nodocs nginx && yum clean all
  16. ---> Running in d2c8fe644415
  17. …………
  18. …………
  19. …………
  20. Step 17/17 : CMD ["/usr/libexec/s2i/usage"]
  21. ---> Running in c24819f6be27
  22. Removing intermediate container c24819f6be27
  23. ---> c147c86f2cb8
  24. Successfully built c147c86f2cb8
  25. Successfully tagged kubespheredev/nginx-centos7-s2ibuilder-sample:latest

As shown above, the builder image has been successfully generated. Now we can run the following command to create the application image:

  1. $ s2i build ./test/test-app kubespheredev/nginx-centos7-s2ibuilder-sample:latest sample-app
  2. ---> Building and installing application from source...
  3. Build completed successfully

Using the logic defined in the assemble script, S2I creates an application image using the builder image as a base and including the source code from the test/test-app directory.

Step 5: Running Application Image

Running the application image is as simple as invoking the docker run command:

  1. docker run -p 8080:8080 sample-app

The Nginx application should now be accessible at http://localhost:8080.

Preview Ngxin

Step 6: Push Image

Push the image nginx-centos7-s2ibuilder-sample to your repository.

Step 7: Create S2I Template

S2I template defines the base environment for building an application, including builder image and runtime image, as well as the environment parameters and destination.

We need to create a yaml file as S2I builder template as follows.

s2ibuildertemplate.yaml

  1. apiVersion: devops.kubesphere.io/v1alpha1
  2. kind: S2iBuilderTemplate
  3. metadata:
  4. labels:
  5. controller-tools.k8s.io: "1.0"
  6. builder-type.kubesphere.io/s2i: "s2i"
  7. name: nginx-demo
  8. spec:
  9. containerInfo:
  10. - builderImage: kubespheredev/nginx-centos7-s2ibuilder-sample
  11. codeFramework: nginx
  12. defaultBaseImage: kubespheredev/nginx-centos7-s2ibuilder-sample
  13. version: 0.0.1
  14. description: "This is a S2I builder template for Nginx builds whose result can be run directly without any further application server.."

Step 8: Use S2I Template in KubeSphere

We can use kubectl to submit the S2I template that we created to KubeSphere.

  1. $ kubectl apply -f s2ibuildertemplate.yaml
  2. s2ibuildertemplate.devops.kubesphere.io/nginx created

When you are done, you can enter the project and create a S2I build. At this point, you will find the custom S2I template of Nginx available in KubeSphere console.

More generally, it is possible to configure any kind of S2I template using S2I CLI, then use the template for quickly build a base environment for building application in batch. There are some more advanced examples you can be found at https://github.com/sclorg/mongodb-container and https://github.com/sclorg/mariadb-container/.