I have a web application on IBM Bluemix. I would like to speed up the app by precompiling the PHP by using Facebook's HHVM. How can this be done? Is this possible on Bluemix?
Thank you,
--
Yeah this actually would be. It would be a little work to do this but with a build pack you can basically run any executable file. You would just need to bind to the port that is assigned by environment variable $PORT. Check out the Cloud Foundry Docs on implementing one. I would take a peak at the C buildpack as well.
The binary buildpack will probably be your best starting place.
You can compile your code using HHVM, I pulled out the relevant pieces from here below. This needs to be done on Ubuntu 14.04 as that is what Bluemix runs on.
Install deps:
sudo apt-get install autoconf automake binutils-dev build-essential cmake g++ gawk git \
libboost-dev libboost-filesystem-dev libboost-program-options-dev libboost-regex-dev \
libboost-system-dev libboost-thread-dev libboost-context-dev libbz2-dev libc-client-dev libldap2-dev \
libc-client2007e-dev libcap-dev libcurl4-openssl-dev libdwarf-dev libelf-dev \
libexpat-dev libgd2-xpm-dev libgoogle-glog-dev libgoogle-perftools-dev libicu-dev \
libjemalloc-dev libmcrypt-dev libmemcached-dev libmysqlclient-dev libncurses-dev \
libonig-dev libpcre3-dev libreadline-dev libtbb-dev libtool libxml2-dev zlib1g-dev \
libevent-dev libmagickwand-dev libinotifytools0-dev libiconv-hook-dev libedit-dev \
libiberty-dev libxslt1-dev ocaml-native-compilers libsqlite3-dev libyaml-dev libgmp3-dev \
gperf libkrb5-dev libnotify-dev
Downloading the HHVM source-code:
git clone git://github.com/facebook/hhvm.git --depth=1
cd hhvm
git submodule update --init --recursive
Build HHVM:
cmake -DMYSQL_UNIX_SOCK_ADDR=/var/run/mysqld/mysqld.sock .
make -j [number_of_processor_cores] # eg. make -j 4
sudo make install
The installed hhvm binary can be found in /usr/local/bin
That's easy to do with the built-in PHP buildpack. Simply specify a dependency on HHVM in your composer.json file, like below:
{
"require": {
"hhvm": ">=3.5"
}
}
Related
I am building an app (PHP/Laravel) that is supposed to be deployed on Google's App Engine. One of the components of the app is to be able to connect to an MSSQL server. Everything worked fine when I was debugging it, but as soon as I deployed it to the App Engine - guess what? It does not work (error: could not find driver).
I went through the Google documentation and I found out that the MSSQL drivers (pdo_sqlsrv, sqlsrv) are not enabled nor available in the standard environment. I checked the flexible environment, but that's the same. The difference is that I can use my own runtime using Dockerfile.
I changed two lines of my app.yaml in the root directory:
runtime: custom
env: flex
Then I created my Dockerfile also in the root directory that was supposed to install sqlsrv and pdo_sqlsrv using PECL and enable it:
FROM gcr.io/google-appengine/php72:latest
ARG COMPOSER_FLAGS='--prefer-dist --ignore-platform-reqs --optimize-autoloader'
ENV COMPOSER_FLAGS=${COMPOSER_FLAGS}
ENV SWOOLE_VERSION=4.3.4
ENV DOCUMENT_ROOT=/app/public
ENV ACCEPT_EULA=Y
COPY . $APP_DIR
RUN apt-get update -y \
&& curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -\
&& curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-release.list \
&& apt-get update -y \
&& apt-get install -y \
unzip \
autoconf \
build-essential \
libmcrypt-dev \
libmpdec-dev \
libpq-dev \
unixodbc-dev \
msodbcsql17 \
mssql-tools \
php-common \
&& apt-get update \
&& pecl install \
decimal \
sqlsrv \
pdo_sqlsrv \
xdebug \
&& apt-get update \
&& phpenmod sqlsrv pdo_sqlsrv \
&& curl -o /tmp/swoole.tar.gz https://github.com/swoole/swoole-src/archive/v$SWOOLE_VERSION.tar.gz -L \
&& tar zxvf /tmp/swoole.tar.gz \
&& cd swoole-src* \
&& phpize \
&& ./configure \
--enable-coroutine \
--enable-async-redis \
--enable-coroutine-postgresql \
--enable-sqlsrv=static --with-pdo_sqlsrv=static \
&& make \
&& make install \
&& chown -R www-data.www-data $APP_DIR \
&& /build-scripts/composer.sh;
ENTRYPOINT ["/build-scripts/entrypoint.sh"]
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
EXPOSE 8080
I also have my own php.ini with two lines in the root directory:
extension = pdo_sqlsrv.so
extension = sqlsrv.so
According to the Google documentation, having this file in the root of an app will extend/replace their default php.ini with my configuration. However, I only found this statement in the docs for non-custom runtimes. I tested it out by changing the value of display_errors and then phpinfo(). The display_errors was still set to the default value and get_loaded_extensions() didn't display sqlsrv nor pdo_sqlsrv.
I checked the build-log and it seems that the drivers were properly installed, because in the 3714 lines I found:
Installing '/opt/php72/lib/x86_64-linux-gnu/extensions/no-debug-non-zts-20170718/sqlsrv.so'
install ok: channel://pecl.php.net/sqlsrv-5.8.1
.....
Installing '/opt/php72/lib/x86_64-linux-gnu/extensions/no-debug-non-zts-20170718/pdo_sqlsrv.so'
install ok: channel://pecl.php.net/pdo_sqlsrv-5.8.1
.....
configuration option "php_ini" is not set to php.ini location
You should add "extension=sqlsrv.so" to php.ini
configuration option "php_ini" is not set to php.ini location
You should add "extension=pdo_sqlsrv.so" to php.ini
Does anybody have any experience with this, please? What do I need to change in the Dockerfile to make Google App Engine enable the PHP extensions?
TL;DR: Add COPY php.ini /opt/php/lib/conf.d/ to Dockerfile.
Google documentation for GAE Standard environment says that you can place php.ini into the root directory, but I didn't find anything like that about Flexible env. Indeed, if you check Configuration File in phpinfo, and related. fields, they show other paths they're looking for php.ini, so you need to place the file there.
When I try that, the custom php.ini is loaded and allows overwriting display_errors, which you mentioned didn't work for you.
Multi-stage build
To avoid shipping C compiler and other build tools to production, which is wasteful and may slow down deployment of your app, you should also use docker's multi-stage build. Basically, you'll build the extensions in one "builder" container and copy the compiled result to the production container.
You Dockerfile will look sth like this:
FROM gcr.io/google-appengine/php72:latest AS builder
RUN apt-get update -y \
&& apt-get install -y \
unzip \
autoconf \
build-essential \
libmcrypt-dev \
libmpdec-dev \
libpq-dev \
unixodbc-dev \
php-common \
&& pecl install \
sqlsrv \
pdo_sqlsrv
FROM gcr.io/google-appengine/php72:latest
# Copy extensions from builder above
ENV PHP_EXT_DIR=/opt/php/lib/x86_64-linux-gnu/extensions/no-debug-non-zts-20170718/
COPY --from=builder $PHP_EXT_DIR/sqlsrv.so $PHP_EXT_DIR/
COPY --from=builder $PHP_EXT_DIR/pdo_sqlsrv.so $PHP_EXT_DIR/
# Install runtime dependencies
ENV ACCEPT_EULA=Y
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -\
&& curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-release.list \
&& apt-get update -y \
&& apt-get install -y \
msodbcsql17 \
mssql-tools
...
I'm not able to install mongodb extension using php:5.6-fpm image.
What's wrong with my Dockerfile configuration ?
FROM php:5.6-fpm
RUN apt-get update \
&& mkdir -p /usr/share/man/man1 \
&& mkdir -p /usr/share/man/man7 \
&& apt-get install -y --no-install-recommends vim curl debconf subversion git apt-transport-https apt-utils \
build-essential locales acl mailutils wget zip unzip htop vim \
gnupg gnupg1 gnupg2 \
libmemcached-dev zlib1g-dev \
libcurl4-openssl-dev pkg-config libssl-dev libicu-dev g++
RUN docker-php-ext-configure intl
RUN docker-php-ext-install pdo pdo_mysql zip intl
RUN pecl install mongodb
RUN docker-php-ext-enable mongodb
COPY php.ini /usr/local/etc/php/conf.d/php.ini
...
...
I have the following error when executing docker-compose build
Step 5/18 : RUN pecl install mongodb
---> Running in 5cd13b1b969c
WARNING: channel "pecl.php.net" has updated its protocols, use "pecl channel-update pecl.php.net" to update
pecl/mongodb requires PHP (version >= 7.0.0, version <= 7.99.99), installed version is 5.6.40
No valid packages found
install failed
Solution:
RUN pecl install mongodb-1.7.4
I have been unable to get soap to work with my php Docker setup.
I am using Docker CE for Windows Version 18.03.1-ce-win65 (17513). PHP version 7.2.3
I've tried running from inside the container apt-get install php-soap which results in
Reading package lists... Done
Building dependency tree
Reading state information... Done*
Package php-soap is a virtual package provided by:
* php7.0-soap 7.0.27-0+deb9u1 [Not candidate version]*
E: Package 'php-soap' has no installation candidate
Running docker-php-ext-install soap
results in the error configure: error: libxml2 not found. Please check your libxml2 installation.
However when looking at php info I see the following:
libxml2 Version => 2.9.4
You will need to install libxml2-dev as part of your dockerfile, the image is kept to a minimum and doesn't include all of the bits needed by every module. Although the image may have the main package, the -dev package includes the components needed to compile other modules which rely on it...
RUN apt-get update && \
apt-get install -y libxml2-dev
(From https://github.com/docker-library/php/issues/315)
Just to make it clear - the command
RUN docker-php-ext-install soap
will then run successfully to install the soap library.
For me, working with PHP 7.3.2, the other solutions didn't work.
Both "php-soap" and "php7.3-soap" got "phpXXX-soap has no installation candidate" error.
Alone "docker-php-ext-install soap" wanted the "libxml2-dev" so i just installed the necessities:
FROM php:7.3
RUN apt-get update -y \
&& apt-get install -y \
libxml2-dev \
&& apt-get clean -y \
&& docker-php-ext-install soap
... and it worked nicely.
The correct answer was done, but for me, I needed also to enable (docker-php-ext-enable soap) the soap module, so for If someone could be useful:
FROM php:7.4.24-apache
# your configurations ...
RUN apt-get update && \
apt-get install -y libxml2-dev
RUN docker-php-ext-install soap && docker-php-ext-enable soap
# other configurations ...
This is outside the scope of this repo.
You should get it via this approach:
RUN apt-get update -y \
&& apt-get install -y \
libxml2-dev \
php-soap \
&& apt-get clean -y \
&& docker-php-ext-install soap
I am using the official php:fpm docker image as base for my application container, so the Dockerfile starts like so:
FROM php:fpm
Later in the file I would like to have something like that:
RUN apt-get install -y \
php7.0-gd
But that tells me:
E: Unable to locate package php7.0-gd
E: Couldn't find any package by regex 'php7.0-gd'
»Bashing« into the container using docker exec -it <name> /bin/bash and executing: apt-cache search php | grep gd yields:
php5-gdcm - Grassroots DICOM PHP5 bindings
php5-vtkgdcm - Grassroots DICOM VTK PHP bindings
php5-gd - GD module for php5
So since that is a debian (yessie) based image, only the old php5 packages are available and php7 is installed by some tricky script in the php:fpm dockerfile and it seams that all extensions are compiled within the used php executable.
How can I install more extensions in this scenario?
Quoting https://hub.docker.com/_/php/
How to install more PHP extensions
We provide the helper scripts docker-php-ext-configure, docker-php-ext-install, and docker-php-ext-enable to more easily install PHP extensions.
To install PHP with iconv, mcrypt and GD, they provide the following example:
FROM php:7.0-fpm
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libmcrypt-dev \
libpng-dev \
&& docker-php-ext-install -j$(nproc) iconv mcrypt \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j$(nproc) gd
Please refer to the Dockerhub page for more details.
I've built a custom Docker image based off an official PHP FPM image php:7.0.14-fpm-alpine
I wanted to keep the size of the image small, so I went for the official alpine PHP-FPM version as it weighs only 27 MB.
I installed only few additional packages through my Dockerfile, and the image grew in size to as much as 277.5 MB. Here is my Dockerfile:
FROM php:7.0.14-fpm-alpine
COPY ./config/www-pool.conf /usr/local/etc/php-fpm.d/www.conf
COPY ./scripts/download-composer.sh /root/download-composer.sh
WORKDIR /root
RUN chmod +x download-composer.sh \
&& ./download-composer.sh \
&& mv composer.phar /usr/local/bin/composer
RUN ["mkdir", "/var/log/php-fpm"]
RUN apk --update add \
autoconf g++ make \
openssl-dev \
libxml2-dev
RUN pecl install \
xdebug \
mongodb
RUN docker-php-ext-enable \
xdebug.so \
mongodb.so
RUN docker-php-ext-install \
pdo_mysql \
soap
RUN addgroup sudo
RUN adduser -S luqo33 -G sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
277.5 MB is a ten-fold increase in size compared to the base image. Apart from Composer, all I needed were several PHP extensions:
mongodb
xdebug
pdo
soap
I'm not sure what contributed the most to increasing the size of my image so much. I suspect that it might be due to the dev dependencies that needed to be installed in order to successfully run pecl (openssl-dev, libxml2-dev), and that might have installed their own tree of dependencies.
Could you please advise on how I can reduce the size of my custom PHP-FPM image and still keep the necessary extensions?
I built the initial part of your image two different ways to test this. A common answer to this question is that the package index takes up extra space. In the case of Alpine Linux (using APK), you can clean up the package index like this:
rm -rf /var/cache/apk/*
However, I built the first part of the image both with and without that cleanup. It made hardly any difference (0.8 MB).
FROM php:7.0.14-fpm-alpine
WORKDIR /root
RUN ["mkdir", "/var/log/php-fpm"]
RUN apk --update add \
autoconf g++ make \
openssl-dev \
libxml2-dev \
&& rm -rf /var/cache/apk/*
Whether the cleanup command is present or not, the image weighs in at 267MB.
REPOSITORY TAG IMAGE ID CREATED SIZE
php-fpm-alpine-test2 latest b87f5e2d629d 23 seconds ago 267.1 MB
php-fpm-alpine-test1 latest 8ff7df8bebea 6 minutes ago 267.9 MB
The space used is simply the packages you're installing.
Step 4 : RUN apk --update add autoconf g++ make openssl-dev libxml2-dev && rm -rf /var/cache/apk/*
---> Running in 037a929d9e6a
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/community/x86_64/APKINDEX.tar.gz
(1/23) Installing m4 (1.4.17-r1)
(2/23) Installing perl (5.22.2-r0)
(3/23) Installing autoconf (2.69-r0)
(4/23) Installing libgcc (5.3.0-r0)
(5/23) Installing libstdc++ (5.3.0-r0)
(6/23) Installing binutils-libs (2.26-r0)
(7/23) Installing binutils (2.26-r0)
(8/23) Installing gmp (6.1.0-r0)
(9/23) Installing isl (0.14.1-r0)
(10/23) Installing libgomp (5.3.0-r0)
(11/23) Installing libatomic (5.3.0-r0)
(12/23) Installing pkgconf (0.9.12-r0)
(13/23) Installing pkgconfig (0.25-r1)
(14/23) Installing mpfr3 (3.1.2-r0)
(15/23) Installing mpc1 (1.0.3-r0)
(16/23) Installing gcc (5.3.0-r0)
(17/23) Installing musl-dev (1.1.14-r14)
(18/23) Installing libc-dev (0.7-r0)
(19/23) Installing g++ (5.3.0-r0)
(20/23) Installing zlib-dev (1.2.8-r2)
(21/23) Installing libxml2-dev (2.9.4-r0)
(22/23) Installing make (4.1-r1)
(23/23) Installing openssl-dev (1.0.2j-r0)
Executing busybox-1.24.2-r11.trigger
OK: 220 MiB in 48 packages
As you can see from the summary at the end of this installation, apk has installed 220 MiB of new content.
My best advice would be to run all of your installation and then you can try to remove some of the packages that are only needed for build, not at run-time. For instance you may not need some of the dev packages anymore, or the compiler, automake, etc.
However, you have to keep in mind that each RUN command makes a new layer. To actually save space this way, you would have to run your apk command, all of your other installs, and the post-install cleanup, in a single RUN command, to make a single layer of it. Otherwise, whether you clean up or not, the earlier layers will still have the content and will still contribute to the image size.
RUN apk --update add \
autoconf g++ make \
openssl-dev \
libxml2-dev \
&& pecl install \
xdebug \
mongodb \
&& docker-php-ext-enable \
xdebug.so \
mongodb.so \
&& docker-php-ext-install \
pdo_mysql \
soap \
&& apk del autoconf g++ make openssl-dev libxml2-dev \
&& rm -rf /var/cache/apk/*