Compiling PHP for use on Lambda

Lambda Docker Containers

AWS Lambda is powered by Docker containers. If you provide a script, Lambda will download the script and execute it within a Docker container. If you provide a zip file, Lambda will download the zip and execute the contents within a Docker contianer.

The docker containers Lambda runs are Amazon Linux. Amazon Lambda does not natively support php, however we can use php if we compile a static single-binary version which can be called by another language that Lambda does support, like NodeJS.

var args    = ['handler.php', JSON.stringify(event), JSON.stringify(contextData)];
var options = {stdio: ['pipe', 'pipe', 'pipe', 'pipe']};
var proc    = child_process.spawn("./php", args, options);

How to compile php 5.6.6 for Lambda

There is an Amazon Linux docker container available. We will download the docker container and use that to compile our php binary.

docker pull amazonlinux:2016.09

Amazon Linux contains the latest security fixes for OpenSSL. However, as of January 2018, the Docker Images used in Lambda do not contain the latest OpenSSL packages. This is a problem because while you will be able to compile your php binary for use with Lambda, you will not be able to run it. To make matters worse, Amazon has removed the previous version of the OpenSSL package from their repositories. So we need a version of PHP compiled against the previous OpenSSL release so that it will run inside of the AWS Lambda docker container.

Getting OpenSSL 1.0.1k

The package is not available in the Amazon Linux Mirrors

Ideally you could solve this issue by downgrading the openssl package and using the yum versionlock plugin to keep the package from being upgraded.

yum install yum-plugin-versionlock

yum versionlock openssl-1.0.1k
yum versionlock openssl-devel-1.0.1k

Unfortunately the outdated openssl-1.0.1k packages are no longer available in the Amazon Linux mirrors. Amazon’s practice of purging the outdated packages from the mirror is not a bad practice, but it does prevent us from getting the package we need to build against.

Using a CentOS package

Luckily Amazon Linux is based on RHEL, so we can substitute a package from CentOS for a relative amount of compatibility. Amazon does upgrade a LOT of the base system so this little trick doesn’t always work. However, in this instance, we are able to locate the packages on http://rpm.pbone.net/

Search results for openssl-libs-1.0.1k-8cnt7.x86_64.rpm :

Filename                                Distribution    File size  
openssl-libs-1.0.1k-8cnt7.x86_64.rpm    CentOS 7        951 kB
openssl-libs-1.0.1k-8cnt7.x86_64.rpm    CentOS Other    951 kB

Build PHP for compatibility with Lambda

##
## Download Bison
##
wget http://ftp.gnu.org/gnu/bison/bison-2.6.4.tar.gz


##
## Download OpenSSL 1.0.1k which is still used by the Lambda Docker image
##
wget ftp://ftp.pbone.net/mirror/rnd.rajven.net/centos/7.0.1406/os/x86_64/openssl-libs-1.0.1k-8cnt7.x86_64.rpm
wget ftp://ftp.pbone.net/mirror/rnd.rajven.net/centos/7/os/x86_64/openssl-devel-1.0.1k-8cnt7.x86_64.rpm


##
## Download the latest PHP
##
PHP_VERSION="php-5.6.33"
wget https://github.com/php/php-src/archive/$PHP_VERSION.tar.gz
tar zxf $PHP_VERSION.tar.gz

##
## Download APD which is used to rewrite
## some PHP functions for use with Lambda
##
cd php-src-$PHP_VERSION
git clone https://github.com/ZeWaren/pecl-apd.git
mv pecl-apd ext/apd
cd ..


##
## Start Amazon Linux Docker Container
##
docker run \
  -e PHP_VERSION="${PHP_VERSION}" \
  -v $(pwd):/srv \
  -ti \
  amazonlinux \
  /bin/bash


##
## Install dependencies needed for compiling PHP
##
yum install -y \
    autoconf \
    automake \
    libtool \
    wget \
    git \
    m4 \
    re2c \
    libxml2-devel \
    openssl-devel \
    libpng-devel \
    libjpeg-devel \
    mysql \
    curl-devel


##
## Install OpenSSL 1.0.1k
##
cd /srv

rpm -ivh --force --nodeps openssl-libs-1.0.1k-8cnt7.x86_64.rpm
rpm -ivh --force --nodeps openssl-devel-1.0.1k-8cnt7.x86_64.rpm




##
## Compile Bison
##
tar -xvzf bison-2.6.4.tar.gz
cd bison-2.6.4
./configure && make && make install

cd /srv




##
## Build PHP
##
cd php-src-$PHP_VERSION
./buildconf --force
ls /lib64/libcrypt*
./configure \
  --enable-static=yes \
  --enable-shared=no \
  --disable-all \
  --enable-apd \
  --enable-dom \
  --enable-filter \
  --enable-hash \
  --enable-json \
  --enable-libxml \
  --enable-mbstring \
  --enable-phar \
  --enable-pdo \
  --enable-simplexml \
  --enable-soap \
  --enable-xml \
  --enable-xmlwriter \
  --enable-zip \
  --with-png-dir=/usr/lib64/libpng12.so.0.49.0 \
  --with-jpeg-dir=/usr/lib64/libjpeg.so.62.0.0 \
  --with-curl \
  --with-gd \
  --with-iconv \
  --with-mysql \
  --with-mysqli \
  --with-pdo-mysql \
  --with-xmlrpc \
  --with-zlib \
  --with-openssl \
  --without-pear \
  --enable-ctype \
  --enable-fileinfo

make -j 5
cp ./sapi/cli/php /srv/

The php binary for use with Lambda is now ready.

categories: AWS | Lambda | PHP |