Tuesday, April 10, 2018

Installing APCu Extension in Openshift Origin PHP Build Image

Background

Openshift Origin is an open-source software developed by Red Hat, that aims to make operating Kubernetes cluster simpler. In Openshift, a base build docker image is used and merged with application source codes to create deployment docker images. Sometimes a software that we need doesn't get included in base build image, which will hamper Openshift adoption.

Base rules

These are a few facts related to docker images, that enables the approach in this blog post :
A. Linux binary from the same operating system release could be copied and used in another Linux OS. In this case we need to create a dummy image with the same OS version of the docker images and copy the relevant PHP extension binary from the image.
B. Some directories are writable during the build process, some are not. When running a build, we do not have full privileges, we are running under a pre-configured default user. When application pods are running it will be running under another configured user. Both user are unable to write to certain directories. Check by executing 'cat > filename' and 'touch filename' commands in Pod console. 
C. Assemble script is going to be run during build time. We will add commands in this script in order to copy files from application source code to certain directories. Sometimes we need to experiment on the assemble script and checking the build logs for errors. Location of original assemble script might be different across platforms.

Initial Condition


For this blog article, we will be using standard Openshift Origin PHP 5.6 build image. Choose Add to Project, PHP, then PHP version 5.6.

Initially we don't have the APC extension in the resulting pods.

Target Condition

We are trying to run a PHP application using APCU extension, with phpinfo screen like this :


How-to

This is achieved by using these files in the application source code .sti/bin directory :

The key to enable extension installation is in the assemble script contents (which must be set to be executable, either locally by chmod u+x assemble or by git update-index ) :

#!/bin/bash
/usr/libexec/s2i/assemble
echo "Assembling.. "
CWD=`pwd`
echo "CWD = $CWD"
echo "short_open_tag=1" >> /etc/opt/rh/rh-php56/php.d/99-opentag.ini
cp .sti/bin/40-apcu.ini /etc/opt/rh/rh-php56/php.d/
ls -l /etc/opt/rh/rh-php56/php.d

The second line calls the original assemble script.
The sixth, create additional ini file for enabling PHP short open tag (which actually outside the context of this blog post). The seventh, copied apcu.ini file to the directory shown by phpinfo as "Scan this dir for additional .ini files".
The contents of apcu.ini actually altered to point to the extension file in the source directory:
; Enable APCu extension module
extension = /opt/app-root/src/.sti/bin/apcu.so

; This can be set to 0 to disable APCu
apc.enabled=1
... other content ..

Now, how do we obtain apcu.so ? My steps are a bit complicated, but for now thats all I have :
(note that you should install docker in your laptop first, create the .sti/bin folder, and change the some-directory to your internal path)
docker run -v /Some-directory/htdocs/application-name/.sti/bin:/tmp --user=root -it openshift/php-56-centos7 bash
Unable to find image 'openshift/php-56-centos7:latest' locally
latest: Pulling from openshift/php-56-centos7
a3ed95caeb02: Pull complete 
bcb99163e835: Pull complete 
6ed5d49af21b: Pull complete 
a2ecf21b138d: Pull complete 
Digest: sha256:abf2f0a2a8bc9919e345f9d311613849295ca5acfb1862042e8f7b49ee211532
Status: Downloaded newer image for openshift/php-56-centos7:latest
bash-4.2# whoami
root
bash-4.2#yum list | grep apc | grep php56 
more-php56-php-pecl-apcu.x86_64           4.0.10-1.el7.centos            remi-php56more-epel-7-x86_64
more-php56-php-pecl-apcu-debuginfo.x86_64 4.0.10-1.el7.centos            remi-php56more-epel-7-x86_64
more-php56-php-pecl-apcu-devel.x86_64     4.0.10-1.el7.centos            remi-php56more-epel-7-x86_64
bash-4.2# yum install more-php56-php-pecl-apcu
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirror.axarva.id
 * epel: epel.mirror.angkasa.id
 * extras: mirror.axarva.id
 * updates: mirror.axarva.id
Resolving Dependencies
--> Running transaction check
---> Package more-php56-php-pecl-apcu.x86_64 0:4.0.10-1.el7.centos will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=========================================================================================================================================
 Package                              Arch               Version                          Repository                                Size
=========================================================================================================================================
Installing:
 more-php56-php-pecl-apcu             x86_64             4.0.10-1.el7.centos              remi-php56more-epel-7-x86_64              64 k

Transaction Summary
=========================================================================================================================================
Install  1 Package

Total download size: 64 k
Installed size: 150 k
Is this ok [y/d/N]: Y
Downloading packages:
more-php56-php-pecl-apcu-4.0.10-1.el7.centos.x86_64.rpm                                                           |  64 kB  00:00:01     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : more-php56-php-pecl-apcu-4.0.10-1.el7.centos.x86_64                                                                   1/1 
  Verifying  : more-php56-php-pecl-apcu-4.0.10-1.el7.centos.x86_64                                                                   1/1 

Installed:
  more-php56-php-pecl-apcu.x86_64 0:4.0.10-1.el7.centos      

Complete!
bash-4.2# rpm -ql more-php56-php-pecl-apcu
/etc/opt/rh/rh-php56/php.d/40-apcu.ini
/opt/rh/rh-php56/root/usr/lib64/php/modules/apcu.so
/opt/rh/rh-php56/root/usr/share/doc/pecl/apcu
/opt/rh/rh-php56/root/usr/share/doc/pecl/apcu/INSTALL
/opt/rh/rh-php56/root/usr/share/doc/pecl/apcu/LICENSE
/opt/rh/rh-php56/root/usr/share/doc/pecl/apcu/NOTICE
/opt/rh/rh-php56/root/usr/share/doc/pecl/apcu/README.md
/opt/rh/rh-php56/root/usr/share/doc/pecl/apcu/TECHNOTES.txt
/opt/rh/rh-php56/root/usr/share/doc/pecl/apcu/TODO
/opt/rh/rh-php56/root/usr/share/licenses/more-php56-php-pecl-apcu-4.0.10
/opt/rh/rh-php56/root/usr/share/licenses/more-php56-php-pecl-apcu-4.0.10/LICENSE
/opt/rh/rh-php56/root/var/lib/pear/pkgxml/more-php56-php-pecl-apcu.xml

bash-4.2# cp /etc/opt/rh/rh-php56/php.d/40-apcu.ini /tmp/40-apcu.ini
bash-4.2# cp /opt/rh/rh-php56/root/usr/lib64/php/modules/apcu.so /tmp/apcu.so
bash-4.2# exit
exit


After copying via the /tmp volume, the files should exist in your .sti/bin folder.

Commit the .sti folder, push to repository, and then rebuild the application. And all should be good to go, but if not, check the build logs and deployed pod logs.

Conclusion

We could install additional extensions in Openshift Origin PHP image by putting the appropriate PHP extension binary in the application source code and creating a sti assemble script.