Tuesday, November 20, 2018

How To Build your Own Openshift Builder Images (saprfc extension for PHP 5.6)

This post shows the steps required to build your own Openshift Builder images. This might be needed when you need to connect to Oracle database using PDO extension, or there is additional command you want to be available in your application pods.
If you simply need additional extension that are readily available, there is an alternative simpler step involving the use of S2I assemble script (see http://inventorsparadox.blogspot.com/2018/04/installing-apcu-extension-in-openshift.html).
But if the extension need nontrivial dependencies, please read the remaining of this blog post.

Tools of the trade

We are going to need Docker toolset available. For Mac users, you could use Docker for Mac. For Windows users, there is Docker for Windows. I will show the screenshot from Docker running on CentOS Linux. You also going to need git (https://git-scm.com/download/win or  https://git-scm.com/download/mac). 

Clone the source repository

First clone the source code repository:
aws@broker ~ $ git clone https://github.com/yudhiwidyatama/s2i-php-container.git
Initialized empty Git repository in /home/aws/s2i-php-container/.git/
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 1201 (delta 0), reused 1 (delta 0), pack-reused 1197
Receiving objects: 100% (1201/1201), 121.52 MiB | 16.52 MiB/s, done.
Resolving deltas: 100% (519/519), done.
aws@broker ~ $ 
After that try to checkout the rfcfull branch :
aws@broker ~ $ cd s2i-php-container/
aws@broker s2i-php-container $ git branch -r
  origin/HEAD -> origin/master
  origin/apm
  origin/master
  origin/pdo_oci8
  origin/pdo_oci8_rfc
  origin/rfc
  origin/rfcfull
aws@broker s2i-php-container $ git checkout rfcfull
Branch rfcfull set up to track remote branch rfcfull from origin.
Switched to a new branch 'rfcfull'
aws@broker s2i-php-container $ git branch
  master
* rfcfull

Build

Lets try to build the image :
aws@broker s2i-php-container $ cd 5.6
aws@broker 5.6 $ docker build -t s2i-php56-rfc .
Sending build context to Docker daemon 
Post http:///var/run/docker.sock/v1.19/build?cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&memory=0&memswap=0&rm=1&t=s2i-php56-rfc: dial unix /var/run/docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?
Seems that the user needs permission to access docker. Check the permission:
aws@broker 5.6 $ ls -l /var/run/docker.sock 
srw-rw----. 1 root root 0 Oct 23  2017 /var/run/docker.sock
It is owned by user root and group root. If you're using Centos, this should do the trick (run as root first):
broker ~ # usermod -aG root aws
broker ~ # 

Now retry (note that need to relogin because of the new group):
broker ~ # su - aws
aws@broker ~ $ id
uid=506(aws) gid=506(aws) groups=506(aws),0(root),490(dockerroot) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
aws@broker ~ $ cd s2i-php-container/
aws@broker s2i-php-container $ cd 5.6
aws@broker 5.6 $ docker build -t s2i-php56-rfc .
Sending build context to Docker daemon 846.8 kB
Sending build context to Docker daemon 
Step 0 : FROM centos/s2i-base-centos7
latest: Pulling from centos/s2i-base-centos7
3993223e10aa: Pull complete 
eb72e5beea78: Pull complete 
9cc5960c49d3: Pull complete 
4b21f2a7e518: Pull complete 
cc56be4d597b: Pull complete 
4d20e7d02f9a: Pull complete 
c8fa6e2ee625: Pull complete 
69852c4e3982: Pull complete 
53a0573f2c8c: Pull complete 
78d20169a434: Pull complete 
3f12a77fa51e: Pull complete 
3fa399969e3d: Pull complete 
581d3e9fafdb: Pull complete 
c240b147d043: Pull complete 
bb83746f161c: Pull complete 
c5013bcc9b43: Pull complete 
59c89aefca2f: Pull complete 
ff41d164f277: Pull complete 
Digest: sha256:a49c3ddec9fd5df400b7ba70075a9c65534bcf4aeab69ff1de18d3c7d16d655b
Status: Downloaded newer image for centos/s2i-base-centos7:latest
 ---> ff41d164f277
Step 1 : EXPOSE 8080
---> Using cache
---> da1f2520288f
Step 2 : ENV PHP_VERSION 5.6 PATH $PATH:/opt/rh/rh-php56/root/usr/bin
---> Using cache
---> f944130c7708
Step 3 : ENV SUMMARY "Platform for building and running PHP $PHP_VERSION applications" DESCRIPTION "PHP $PHP_VERSION available as docker container is a base platform for building and running various PHP $PHP_VERSION applications and frameworks. PHP is an HTML-embedded scripting language. PHP attempts to make it easy for developers to write dynamically generated web pages. PHP also offers built-in database integration for several commercial and non-commercial database management systems, so writing a database-enabled webpage with PHP is fairly simple. The most common use of PHP coding is probably as a replacement for CGI scripts."
---> Using cache

...
Step 17 : USER 1001
 ---> Running in 0dca667bb85f
 ---> 199df5b9f228
Removing intermediate container 0dca667bb85f
Step 18 : CMD $STI_SCRIPTS_PATH/usage
 ---> Running in 922e0b45384a
 ---> 666d38e20eeb
Removing intermediate container 922e0b45384a
Successfully built 666d38e20eeb



So the build was a success, now we only need to publish to Docker Hub. It actually isn't a mandatory to publish to docker hub, but the alternative is to publish to Openshift Internal Registry which is not quite  simple.

Publishing to Docker Hub

First examine that the image already built successfully :
aws@broker 5.6 $ docker images | grep s2i-php56-rfc
s2i-php56-rfc                                                                latest              666d38e20eeb        3 minutes ago       711.6 MB
Then retag the image (note: you should replace 'yudhiwidyatama' with you docker hub username):
aws@broker 5.6 $ docker tag s2i-php56-rfc yudhiwidyatama/s2i-php56-rfc:201801
Finally push the image, logging in along the way:
aws@broker 5.6 $ docker push yudhiwidyatama/s2i-php56-rfc:201801
The push refers to a repository [yudhiwidyatama/s2i-php56-rfc] (len: 1)
666d38e20eeb: Image push failed 

Please login prior to push:
Username: yudhiwidyatama
Password: 
Email: y**********@somewhere.com
WARNING: login credentials saved in /home/aws/.docker/config.json
Login Succeeded
The push refers to a repository [yudhiwidyatama/s2i-php56-rfc] (len: 1)
666d38e20eeb: Image already exists 
199df5b9f228: Image successfully pushed 
45071d907359: Image successfully pushed 
78405a7ecddd: Image successfully pushed 
1ba9df30e3cc: Image successfully pushed 
25d1fdac92c5: Image successfully pushed 
af57e9dca950: Image successfully pushed
c43b674aaedb: Image successfully pushed 
bb63b43c6289: Image successfully pushed 
8662170845ba: Image successfully pushed 
41771e55d58f: Image successfully pushed 
30713c6eb336: Image successfully pushed 
72906bd3915f: Image successfully pushed 
e071aabb7f3d: Image successfully pushed 
8a7c8fc193ee: Image successfully pushed 
247b1e7eeb1b: Image successfully pushed 
f944130c7708: Image successfully pushed 
da1f2520288f: Image successfully pushed 
...
59c89aefca2f: Image successfully pushed 
c5013bcc9b43: Image already exists 
bb83746f161c: Image already exists 
c240b147d043: Image already exists 
581d3e9fafdb: Image successfully pushed 
3fa399969e3d: Image already exists 
3f12a77fa51e: Image already exists 
78d20169a434: Image already exists 
53a0573f2c8c: Image successfully pushed 
69852c4e3982: Image successfully pushed 
c8fa6e2ee625: Image already exists 
4d20e7d02f9a: Image already exists 
cc56be4d597b: Image already exists 
4b21f2a7e518: Image already exists 
9cc5960c49d3: Image already exists 
eb72e5beea78: Image already exists 
3993223e10aa: Image successfully pushed 
Digest: sha256:b75d330d04b8b66a5231b9efd4082f684291eaff2906d956ab8f24f4b661b843

This process takes a while, even hours if your upload internet connection is slow. Now you could see the image successfully uploaded to Docker Hub :

Conclusion

In this blog I have shown how to build a rfc-enabled PHP 5.6 S2I  image using docker and upload the image to dockerhub.

The hard part

Actually I haven't discussed how to actually modify the docker image. The modification is in the lines 48-70 of the Dockerfile file.

The first three lines is to prepare directories that are we going to use in compiling the saprfc PHP extension :

RUN mkdir /opt/app-root/sap
RUN mkdir -p /usr/sap/rfcsdk
RUN mkdir /opt/app-root/saprfc-ext

The next two lines to add files from SAP's RFC SDK (extracted from file RFC_60-10003377.SAR from SAP Support) and PHP saprfc source code from http://saprfc.sourceforge.net/ :
ADD ./rfcsdk.tar.gz /usr/sap
ADD ./saprfc.tar.gz /opt/app-root

Note that the tar.gz file must be put in the same directory as the Dockerfile (check the github repo for resulting tar.gz).
Afterwards, install PHP 5.6 development package with the required compatibility library.

RUN yum install -y centos-release-scl && \
    INSTALL_PKGS="rh-php56-php-devel compat-libstdc++-33" && \
    yum install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \
    rpm -V $INSTALL_PKGS && \
    yum clean all -y

The compilation process is done using phpize, configure, and make install.

RUN cd /opt/app-root/saprfc && \
 phpize && \
 ./configure && \
 make && \
 make install && \
 make clean

To enable the extension, an INI file is needed :

RUN echo "extension=saprfc.so" > /etc/opt/rh/rh-php56/php.d/99-saprfc.ini

And that is how you customize the Dockerfile.

No comments: