I'm trying to create a Docker image based on Alpine Linux which will run PHP 7.1 (apk add php7=7.1.9-r0) with some modules installed (memcached, mongodb, oauth, openssl and redis).
I install the modules through PECL like this:
RUN yes | pecl install \
igbinary \
redis-3.1.4 \
oauth-2.0.2 \
memcached-3.0.4 \
mongodb-1.3.3
Then add each of them to php.ini.
RUN for EXT in \
igbinary \
memcached \
mongodb \
oauth \
openssl \
redis; \
do \
echo "extension=${EXT}.so" >> /etc/php7/php.ini; \
done
Most modules install correctly, but memcached and redis don't want to play along:
# php -v
PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php7/modules/memcached.so' - Error relocating /usr/lib/php7/modules/memcached.so: php_session_create_id: symbol not found in Unknown on line 0
PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php7/modules/redis.so' - Error relocating /usr/lib/php7/modules/redis.so: php_session_register_module: symbol not found in Unknown on line 0
PHP Warning: Module 'openssl' already loaded in Unknown on line 0
PHP Warning: Cannot load module 'mongodb' because required module 'json' is not loaded in Unknown on line 0
PHP 7.1.9 (cli) (built: Oct 2 2017 20:51:54) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
I've also tried from source:
RUN git clone https://github.com/php-memcached-dev/php-memcached
RUN cd php-memcached \
&& git checkout php7 \
&& git pull \
&& /usr/bin/phpize \
&& ./configure --with-php-config=/usr/bin/php-config \
&& make \
&& make install
This however gives me the same result. I've done some searching and apparently there might be some related problem of glibc on Alpine (example thread) but I'm not quite sure this is the same issue as the error output is a bit confusing.
Is there anything I'm overlooking as to how these modules should be installed to work with PHP 7.1 on Alpine Linux?
All of these extensions are available in Alpine repositories, so why are you making your life harder and installs them directly from PECL? Install them simply using apk.
php7-redis
php7-oauth
php7-memcached
php7-mongodb (currently only in testing repository)
php7-openssl
Note that these packages are in Alpine v3.7 (the latest stable release), I haven’t checked if they are available also in older releases.
These packages, of course, installs config files with extension=<ext>.so, so don’t add it manually to php.ini.
apk add php7=7.1.9-r0
Why do you specify exact version? This will fail once we update the package (e.g. with security patches), because only the latest version of packages is available in the repositories. We backport only security fixes and bugfixes (i.e. patch versions) into stable releases, so there will not be 7.2.x in v3.6 or v3.7.
PHP 7.2 And onward are based on Alpine 3.7 Wich has all the necessary extensions available in the repository.
However there are PHP 7.1 and PHP 7.0 Which are still based on 3.4 which does not have any php7-* extensions.
Workaround is to install pecl and which in turn can install all necessary extensions.
You can achieve this in this way:
RUN apk update\
&& apk upgrade \
&& apk add libmemcached \
libmemcached-libs \
libmemcached-dev \
build-base \
zlib-dev \
php5-dev \
git \
autoconf \
cyrus-sasl-dev \
&& pecl config-set php_ini /usr/local/etc/php/php.ini \
&& pecl install -f memcached \ #Add any Additional packages
&& echo extension=memcached.so >> /usr/local/etc/php/conf.d/docker-php-ext-memcached.ini \
&& rm -rf /tmp/pear \
&& apk del php5-dev \
build-base \
zlib-dev \
php5-dev \
git \
autoconf \
cyrus-sasl-dev
This will install PECL with php5 which works perfectly to install extensions for PHP 7+
And dont forget to include your packages
We were facing similar issues with the "official" PHP images build on Alpine. Ie. it was impossible for us to install a working ImageMagick version in PHP 7.1 which is based on Alpine 3.4
What we did is installing it from Alpine 3.6, while I actually won't recommend this it might be a workaround.
The other workaround is to wait for PHP 7.2 which is build on Alpine 3.6. Might be an option to look for a working PHP + Alpine combination, since you are building FROM alpine and not FROM php:alpine
Just saying: Issues like that made us go back to Debian images, since we've wasted tons of hours on that, including weird glibc issues like you mentioned.
Related
I have set up a Symfony4 project with in a Docker container.
I followed the Jobeet-Tutorial where they use the phpdocker.io - generator.
All works perfect but very slow. So I want to speed up and enable the opcache and configure it.
I found helpful links in the net. So I added to my Dockerfile this:
RUN docker-php-ext-configure opcache --enable-opcache \
&& docker-php-ext-install opcache
# Copy configuration
COPY config/opcache.ini $PHP_INI_DIR/conf.d/
The problem is that I don't have this helperscripts:
docker-php-ext-configure
docker-php-ext-install
docker-php-ext-enable
So I decided to search it in the internet and copy it into my project.
Now I have it in the php-fpm folder of my docker directory.
My directory looks like this now - the scripts are in the beneath the Dockerfile:
Is there any other step I forgot to do, like registering these scripts somewhere?
The most immediate answer to your question is that you need to copy those scripts into the Docker image you are building. To do that, you should create a subdirectory within the php-fpm directory named bin and put all of those scripts in that directory. Then, in your Dockerfile:
COPY bin /usr/local/bin
Now when you try to use that image, the scripts will be within your executable PATH.
However
Those docker-php-ext-* scripts you found are from the PHP project's official Docker images and are intended to be used with those images.
You are using the phpdockerio/php73-fpm:latest image, which seems to use ubuntu:bionic as a base image. These scripts depend heavily on the PHP Dockerfiles, which do a bunch of preparatory steps, such as downloading the source code for the PHP interpreter itself to /usr/src. Making these scripts run directly in a phpdockerio container would be a very involved process.
That leaves you with 2 options:
Forgo the scripts and install Ubuntu's prebuilt packages. You seem to already have the apcu, apcu-bc, cli, curl, json, mbstring, opcache, readline, xml, and zip PHP extensions installed. You can see the full list of packages that are available from the default repos this way by running
docker run --rm -it phpdockerio/php73-fpm:latest bash -c 'apt-get update && apt search ^php7.3-';
When you know which packages you want, you can add them to your Dockerfile.
Switch to using an official PHP image instead so you can use the docker-php-ext-* scripts. The phpdocker-io image you are using is essentially PHP7.3-FPM on Ubuntu, and the closest official PHP image to that is php:7.3-fpm-stretch (Debian 9). You can build and install the extensions listed in Option 1 by changing your PHP-FPM Dockerfile to:
FROM php:7.3-fpm-stretch
# Run in Bash instead of Bourne shell to get lists
RUN ["bash", "-c", " \
#Exits on error or unbound variable. Now we can use semicolons instead of
#ampersands
set -eu; \
\
ext_build_dependencies=( \
#Needed to build php-curl
libcurl4-gnutls-dev \
\
#Needed to build php-mbstring
libedit-dev \
\
#Needed to build php-xml \
libxml2-dev \
\
#Needed to build php-zip
zlib1g-dev libzip-dev \
); \
\
apt-get update; \
apt-get install -y ${ext_build_dependencies[#]}; \
\
#Build the extensions
docker-php-ext-install curl json mbstring readline xml zip ; \
pecl install apcu apcu_bc; \
\
apt-get purge -y ${ext_build_dependencies[#]}; \
apt-get autoremove -y; \
apt-get clean -y; \
"]
If Ubuntu 18 and Debian were binary-compatible (they're not), you could try a third option, which would be building the extensions using a PHP image, then copying over the built extensions as the second stage of a multi-stage build. This would be possible if your image uses the same Linux flavor as as the PHP image does. For example, if your image were based on alpine:3.8, you could use php:7.3-fpm-alpine3.8 to build your extensions and copy them over.
I'm using wordpress:php7.1-fpm-alpine which is based on php:7.1-fpm-alpine (https://github.com/docker-library/wordpress/blob/master/php7.1/fpm-alpine/Dockerfile).
I've tried RUN pecl install xdebug-2.5.0 && docker-php-ext-enable xdebug
which results in an error when building:
Step 19/19 : RUN pecl install xdebug-2.5.0 && docker-php-ext-enable xdebug
---> Running in 52c988e12cb2
downloading xdebug-2.5.0.tgz ...
Starting to download xdebug-2.5.0.tgz (267,640 bytes)
........................................................done: 267,640 bytes
76 source files, building
running: phpize
Configuring for:
PHP Api Version: 20160303
Zend Module Api No: 20160303
Zend Extension Api No: 320160303
Cannot find autoconf. Please check your autoconf installation and the
$PHP_AUTOCONF environment variable. Then, rerun this script.
The following is sufficient for simply installing xdebug on that image:
FROM wordpress:php7.1-fpm-alpine
RUN apk add --no-cache $PHPIZE_DEPS \
&& pecl install xdebug-2.5.0 \
&& docker-php-ext-enable xdebug
Building that and then running from a shell inside the resulting image produces the following:
$ php -i | grep Xdebug
with Xdebug v2.5.0, Copyright (c) 2002-2016, by Derick Rethans
If you are concerned about image size you can remove the dependencies:
FROM wordpress:php7.1-fpm-alpine
RUN apk --update --no-cache add autoconf g++ make && \
pecl install -f xdebug && \
docker-php-ext-enable xdebug && \
apk del --purge autoconf g++ make
Great answer #msanchez_aplyca. Although more correctly removing the build dependancies via apk would be:
RUN apk add --no-cache --virtual .build-deps $PHPIZE_DEPS \
&& pecl install xdebug-2.5.0 \
&& docker-php-ext-enable xdebug \
&& apk del -f .build-deps
For PHP >= 7.2 you need to use Xdebug 2.6.0+
For example, install the Xdebug 3.0.0 (released on the 25th November 2020)
Compatible with PHP 8.0
RUN apk add --no-cache --virtual .build-deps $PHPIZE_DEPS \
&& pecl install xdebug-3.0.0 \
&& docker-php-ext-enable xdebug \
&& apk del -f .build-deps
Now you set it up by adding something like (using Xdebug 3.0.0 syntax, more info here):
# Configure Xdebug
RUN echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo "xdebug.mode=debug" >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo "xdebug.log=/var/www/html/xdebug/xdebug.log" >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo "xdebug.discover_client_host=1" >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo "xdebug.client_port=9000" >> /usr/local/etc/php/conf.d/xdebug.ini
xdebug can be installed via apk, but it takes some tweaking
Determine your PHP extension and config directories
Copy the output of php -i to your clipboard.
Go to the xdebug Installation Wizard and paste the results in the box.
Keep this output handy, as we'll need it later. We are mainly concerned with Extra Configuration Files Path and Extensions directory.
Sample xdebug installation wizard output
Figure out where the apk package is being installed
Your results may vary depending on the version you select.
You can find available versions by reviewing the xdebug documentation. As of this writing, only the major PHP releases are listed, but I was able to manually specify a feature release. Just don't include the dot (e.g., 81 NOT 8.1).
Run apk info -a php<your-php-version>-pecl-xdebug to get the contents of the package.
According to the output of apk info -a php81-pecl-xdebug, my locations were:
php81-pecl-xdebug-3.1.5-r0 contains:
etc/php81/conf.d/50_xdebug.ini
usr/lib/php81/modules/xdebug.so
Create your xdebug configuration
I like to keep my xdebug.ini inside my VS Code .devcontainer folder, so that's the route I'll follow for this example. You can also create the configuration file directly in its destination.
If you take the latter path, name the file 99-xdebug.ini per the documentation.
In either case, all you really need is this line to enable xdebug.
zend_extension=xdebug
Additional options are needed to make it do anything useful, but I'll leave that to the reader.
Create your Dockerfile
In your dockerfile, install the package and link/copy the files according to the previous steps. For example:
ADD <local_xdebug.ini_path> <PHP Extra Configuration Files Path>99-xdebug.ini
RUN apk update && apk add php<version>-pecl-xdebug && \
ln -s /<apk_xdebug.so_path> \
<PHP Extensions directory>
In my case:
ADD ./xdebug.ini /usr/local/etc/php/conf.d/99-xdebug.ini
RUN apk update && apk add php81-pecl-xdebug && \
ln -s /usr/lib/php81/modules/xdebug.so \
/usr/local/lib/php/extensions/no-debug-non-zts-20210902/xdebug.so
Rebuild the container and verify xdebug is enabled
After rebuilding the container, verify that the xdebug module is installed by running php -m
I'm a PHP dummy, so I used the xdebug Installation Wizard as before to verify xdebug was enabled.
Hopefully this saves someone else a couple frustrating hours.
xdebug installed
When I run the this command 'php -r "readfile('https://getcomposer.org/installer');" | php' on Cygwin terminal. The following errors have been triggered on the terminal:
Some settings on your machine make Composer unable to work properly.
Make sure that you fix the issues listed below and run this script again:
The json extension is missing.
Install it or recompile php without --disable-json
The phar extension is missing.
Install it or recompile php without --disable-phar
The iconv OR mbstring extension is required and both are missing.
Install either of them or recompile php without --disable-iconv
However, all these extensions are enabled in php.ini file. I am using XAMPP.
I think you need to install the correct php extensions ...
apt-cyg install \
php \
php-json \
php-phar \
php-mysql \
php-curl \
php-gd \
php-intl \
php-imap \
php-mcrypt \
php-pspell \
php-recode \
php-tidy \
php-xmlrpc \
php-xsl
PS: I created a install-script for this :) https://github.com/voku/dotfiles/blob/master/firstInstallCygwin.sh
I am compiling php7 from source and have pre compiled a number of dependencies in /home/mybin for example I have openssl in
/home/mybin/bin/openssl
/home/mybin/include/openssl/*.h
I have also readline as
/home/mybin/include/readline/readline.h
using the php compile options
./configure \
CC=/home/mybin/bin/gcc \
--prefix=/home/_cgi/php7 \
--bindir=/home/mybin/bin \
--libdir=/home/mybin/lib \
--with-libdir=/home/mybin/lib64 \
--includedir=/home/mybin/include \
--include-openssl \
i have tried the following options for readline
--with-readline=/home/mybin/include/readline
OR
--with-readline=/home/mybin/
OR
--with-readline
all variations end with configure: error: Please reinstall readline - I cannot find readline.h
All other dependencies built from source and in /home/mybin are found no problem. Can you suggest what flag I sould set so readline.h can be found?
thx Art
On Debian-9 first, I installed libreadline-dev package using
apt-get install libreadline-dev
and then when searching for the path of readline.h using command
dpkg -S readline.h
It gave me below output:
nodejs: /usr/share/doc/nodejs/api/readline.html
libreadline-dev:amd64: /usr/include/readline/readline.h
So the file is located in /usr directory
Finally I configured php using --with-readline=/usr and everything was fine.
for readline you need to install
sudo apt install -y libedit-dev libreadline-dev
please see http://stackoverflow.com/questions/35891777/linux-correct-flag-to-pass-gcc-mcrypt-h-location for a good description of how to fix this issue as both are related
I have a Docker container that runs PHP-FPM 5.5 and I'd like to ensure that it has access to the Couchbase SDK. I have this working outside of Docker and can't really picture how Docker would interfere and yet I seem to be running into a problem that is "probably" docker related:
My Docker container runs under Ubuntu 14.04 and includes the following installation (after installing PHP):
# Install Couchbase C-library and PECL extension
RUN wget -O/etc/apt/sources.list.d/couchbase.list http://packages.couchbase.com/ubuntu/couchbase-ubuntu1404.list \
&& wget -O- http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add - \
&& apt-get update \
&& apt-get install -y --no-install-recommends pkg-config libcouchbase2-libevent libcouchbase-dev libmemcached-dev php-pear php5-dev make \
&& pecl config-set php_ini /app/conf/php.ini \
&& pecl install couchbase --alldeps \
&& pecl install memcached --alldeps \
&& { \
echo "; Couchbase PHP SDK"; \
echo "extension=/usr/lib/php5/20121212/couchbase.so"; \
} > /etc/php5/fpm/conf.d/30-couchbase.ini \
&& cp /etc/php5/fpm/conf.d/30-couchbase.ini /etc/php5/cli/conf.d \
&& { \
echo "; Memcached PHP SDK"; \
echo "extension=/usr/lib/php5/20121212/memcached.so"; \
} > /etc/php5/fpm/conf.d/30-memcached.ini \
&& cp /etc/php5/fpm/conf.d/30-memcached.ini /etc/php5/cli/conf.d
This SHOULD install both the C-libraries and the PECL extensions for Couchbase and Memcached support. In many ways it DOES appear to:
php -m does include these modules as installed,
and phpinfo() reports on their configuration as such:
However, whenever I try to instantiate either a Couchbase or Memcached class can't find the class. So if I run the following program:
<?php
$foo = new Couchbase();
$bar = new Memcached();
print_r($foo);
print_r($bar);
?>
it gives me the following error:
PHP Fatal error: Class 'Couchbase' not found in /app/test.php on line 2
UPDATE: It turns out, however, that while Couchbase does not work, Memcached does. Not sure if that helps or hurts the troubleshooting but Couchbase seems to be the exclusive pain point.
The answer, it appears, has to do with Couchbase moving from their 1.x to 2.x SDK's which in the case of PHP means that there is no longer a class called "Couchbase".
The longer term answer will be to migrate to this new API; which does look like it will require some work. In the near term, however, I needed a solution that would work for my existing use of Couchbase and that is quite simple ... just install the right version of Couchbase:
pecl install couchbase-1.2.2
That's all that was needed for me. You can see a working Docker of this setup at: lifegadget/docker-php
Note: the default version of the SDK you get from PECL is now 2.0 so if you're not specifying a version you're getting version 2.x.