Where to store the docker-php-ext files? - php

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.

Related

Install mongodb driver in docker with dockerfile

I have a mongodb docker container. I need another docker container which will have php and apache installed. I want to run a php script from this container and send some data to the mongodb container to save the data in mongodb database. So i need to install mongodb driver in the php-apache container.
To do that, i have created following dockerfile:
FROM php:7.3-apache
COPY src/ /var/www/html
RUN apt-get update
RUN apt-get install openssl libssl-dev libcurl4-openssl-dev
RUN pecl install mongodb
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini
RUN echo "extension=mongodb.so" > /usr/local/etc/php/php.ini
EXPOSE 80
It first builds php-apache docker image. Then it should install mongodb driver.
But when i run the following command
docker build -t my-mongo .
At one point it shows following message and stops the execution:
Need to get 2213 kB of archives.
After this operation, 9593 kB of additional disk space will be used.
Do you want to continue? [Y/n] Abort.
The command '/bin/sh -c apt-get install openssl libssl-dev libcurl4-openssl-dev' returned a non-zero code: 1
What went wrong here? Is there anything wrong in the dockerfile ?
What went wrong here? Is there anything wrong in the dockerfile ?
There are at least three things wrong with your Dockerfile IMO.
The first one is not in direct relation to your problem, but you are creating way too many layers (one for each RUN command) for something as simple as adding a driver to your image. You should put all this in a single layer (i.e. a single RUN command) and cleanup after yourself at the end to keep the layer footprint small.
Now the core of your real problem. As you can see in your output, apt-get is launched in interactive mode and asks for a confirmation. The docker build process can't handle that and therefore aborts the command causing the build to fail. To overcome this, apt-get has a -y option to answer 'yes' to all prompts by default.
The last one is in the line where you add the mongo driver to php.ini: you are redirecting echo output to your file with a single gt; sign (>), hence you are replacing the full content of the file you just copied. You must use a double gt; sign (>>) for content to be appended.
The following Dockerfile should fix the problems above (tested without the copy of sources + cp of your own php.ini file since I don't have them)
FROM php:7.3-apache
COPY src/ /var/www/html
RUN apt-get update \
&& apt-get install -y --no-install-recommends openssl libssl-dev libcurl4-openssl-dev \
&& pecl install mongodb \
&& cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini \
&& echo "extension=mongodb.so" >> /usr/local/etc/php/php.ini \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
EXPOSE 80
Some explanation:
The && notation allows to run all commands one after the other in a single docker RUN command resulting in a single intermediate container, thus a single layer.
-y --no-install-recommends options to apt-get ask apt to not go interactive (answer yes everywhere) and to install only needed packages, not the recommended ones.
The two last instruction apt-get cleann && rm -rf /var/lib/apt/lists/* remove all caches made by running apt so that the layer stays as small as possible. (see apt-get chapter in docker best practice)
put this at the beginning of your Docker file, it is important to have it before installing all other extensions, otherwise it fails.
FROM php:7.3-apache
RUN apt-get update -y && apt-get upgrade \
&& pecl install mongodb && docker-php-ext-enable mongodb
That's all what I needed to get mongodb running FROM php:7.3-cli-buster Probably it will work for other versions - fpm, apache etc as well.

What do docker-php-ext-configure, docker-php-ext-install and docker-php-ext-enable do?

I'm trying to set up a LAMP web server using docker and was delighted to discover that the good folks over at php have put together a docker container for php.
Reading through the documentation I found three functions that will ostensibly assist me with the installation of php extensions;
docker-php-ext-configure
docker-php-ext-install
docker-php-ext-enable
Being a complete newcomer to php and having tried and failed to enable php modules using a combination of apk add and php.ini hackery (resulting in .so not found errors), I'm ready to admit defeat and do it the proper way.
Unfortunately, the documentation is remarkable vague about what these commands do and how to use them:
We provide the helper scripts docker-php-ext-configure,
docker-php-ext-install, and docker-php-ext-enable to more easily
install PHP extensions.
I tried to google it as well, but couldn't find any useful resources online either.
I'm now completely confused between what it means to install, configure and install a php extension, and how commands like apk add php7-* relate to all of this.
Please explain what these functions do, and how you would use them to enable php extensions.
These are helper scripts that helps one install php extensions from source
not all extensions are available in a distribution native package manager or pecl
even if these exist one may want to configure these differently or optimize
Talking about the scripts
docker-php-ext-configure - configure an extension before you build it with docker-php-ext-install. It's executed by docker-php-ext-install, so one should use it if wants to override the defaults
docker-php-ext-install - build extension from source, usually executes docker-php-ext-configure for build configuration, enables the extension (php.ini entry) by executing docker-php-ext-enable after all
docker-php-ext-enable - enables an already extension by adding a specific entry to php.ini. Extensions installed with pecl or native package managers may not be enabled by default thus require this additional step. As mentioned above, extensions installed with docker-php-ext-install are being enabled automatically.
these functions can help to set-up your PHP configuration, if per example
you want to add opcache to your PHP configuation:
firstly you configure as below :
docker-php-ext-configure gd \
--enable-gd-native-ttf \
--with-jpeg-dir=/usr/lib \
--with-freetype-dir=/usr/include/freetype2 && \
docker-php-ext-install gd \
and you install your configuration
&& docker-php-ext-install opcache
and then you can enable it
&& docker-php-ext-enable opcache
I had the same question and wasn't satisfied with the level of details of other answers.
The code of the docker-php-ext-install and other utilities is in the PHP docker images. Some examples:
php7.3-apache: https://github.com/docker-library/php/tree/master/7.3/buster/apache
php7.3-fpm: https://github.com/docker-library/php/tree/master/7.3/buster/fpm
php7.3-alpine: https://github.com/docker-library/php/tree/master/7.3/alpine3.12/fpm
docker-php-ext-install in php7.3-fpm has these interesting parts (omitting option parsing, etc.):
docker-php-source extract
cd /usr/src/php/ext
# skip usage, option parsing and checking the extension list
for ext in $exts; do
cd "$ext"
[ -e Makefile ] || docker-php-ext-configure "$ext"
make -j"$j"
make -j"$j" install
find modules \
-maxdepth 1 \
-name '*.so' \
-exec basename '{}' ';' \
| xargs -r docker-php-ext-enable ${iniName:+--ini-name "$iniName"}
make -j"$j" clean
cd "$popDir"
done
So this means the -j$(nproc) I see everywhere specifies that the number of make jobs (commands) to run simultaneously is the same as the number of processors.

Execute a build-in PHP server file with Docker

I have a php application in Github, and I want to create a Docker image to, automaticaly, clone this application and run a custom server php file (react-php implemented).
This is my point of start.
FROM php:7.1-cli
RUN apt-get update && \
apt-get install -y \
libzip-dev \
zip \
&& docker-php-ext-configure zip --with-libzip \
&& docker-php-ext-install zip bcmath
RUN apt-get install -y \
git-core \
curl && \
git clone https://github.com/xxx/xxx.git myfolder && \
cd myfolder && \
curl -sS https://getcomposer.org/installer | php && \
php composer.phar install
EXPOSE 8000
CMD ["php bin/server"]
This code allows me to build the image, but when I run this image in a container, then I'm not being able to execute the file.
/usr/local/bin/docker-php-entrypoint: 9: exec: php bin/server: not
found
Maybe it's because I don't barely understand some bases of Docker, but it's getting hard for me to make this happen.
Any help on that, please?
According to the official docker documentation for CMD, you should try to modify the last line of your Dockerfile to either CMD php bin/server or CMD ["php", "bin/server"]
Furthermore if you want your commands to be executed with a relative path, you should consider setting the working directory with the WORKDIR directory command before using RUN, CMD, ENTRYPOINT, COPY or ADD.

Docker - How to disable PHP ext / modules

I am working on a PHP API and I would like to disable unused php Modules inside my PHP-FPM image, such as "sqlite3, pdo ..".
I am a docker beginner and I would like to know if is there anything similar to docker-php-ext-enable if not what is the best practice for disabling unused php modules.
Finally I found the key point.
Inside docker php container, all the registered modules holds by a configuration file under the below path.
/usr/local/etc/php/conf.d/*.ini
bash into the container:
docker exec -it php_container_name bash
You can list all the enabled modules by php -m:
And cd into that folder, you can see the relating config files:
cd /usr/local/etc/php/conf.d/
ls
# output
docker-php-ext-mcrypt.ini docker-php-ext-mysqli.ini
docker-php-ext-opcache.ini opcache-recommended.ini
docker-php-ext-zip.ini
To disable some extension module, make a dir disabled, and move that .ini file inside it, for example:
mkdir disabled
mv docker-php-ext-opcache.ini disabled
mv opcache-recommended.ini
Finally, press Ctrl+D to exit the container, and then restart the container to make changes work.
docker restart php_container_name
You can get into the container and run php -m to see, the relating extension is gone.
Piggybacking off Alfred's answer but I made these today.
alias disDebugCust="docker exec -it xdebugContainer bash -c 'cd /usr/local/etc/php/conf.d/ && mkdir -p disabled && mv xdebug.ini disabled && /etc/init.d/apache2 reload'"
alias enDebugCust="docker exec -it xdebugContainer bash -c 'cd /usr/local/etc/php/conf.d/disabled && mv xdebug.ini /usr/local/etc/php/conf.d/ && /etc/init.d/apache2 reload'"
First we exec into the container.
Then we go to the config folder.
Then we make a new directory called disabled if one doesn't exist.
Then we move the ini file.
Finally we restart apache.
The second command just moves it back and restarts apache.
In my case i had to enable/disable xdebug extension. I appears that there's some 'magic' that works by (de-)suffixing extensions ini file with -disabled.
Once the suffix changes, php somehow magically loads/unloads module. You can check that by running php -m command. (maybe this behaviour is only alpine-linux related??)
I wrote additional docker-php-ext-disable-xdebug script by taking example from /usr/local/bin/docker-php-ext-enable-xdebug:
#!/bin/sh
if test -f '/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini'; then
echo 'Disabling extension xdebug'
mv '/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini' '/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini-disabled'
else
echo 'The extension xdebug is not enabled'
fi
Yes that's possible.
Taken from https://hub.docker.com/_/php/
For example, if you want to have a PHP-FPM image with iconv, mcrypt and gd extensions, you can inherit the base image that you like, and write your own Dockerfile like this:
FROM php:7.0-fpm
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libmcrypt-dev \
libpng12-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
Remember, you must install dependencies for your extensions manually. If an extension needs custom configure arguments, you can use the docker-php-ext-configure script like this example.

How to add Zend Guard Loader support in docker php official image instance?

I want to add Zend Guard Loader support on my php instance.
http://www.zend.com/en/products/loader/downloads#Linux
Normally, I will download the package, and then add the following settings into php.ini
[Zend Guard Loader]
zend_extension="/usr/local/webserver/php/ext/ZendGuardLoader.so"
zend_loader.enable=1
zend_loader.disable_licensing=0
zend_loader.obfuscation_level_support=3
zend_loader.license_path="/var/developer.zl"
But, now I'm running the instance within docker.
docker run --name php_instance php:5-fpm
And I tried to get into the shell:
docker exec -it php_instance bash
But I cannot find the php.ini, how can I make it work?
Did you add a command in your Dockerfile to copy the php.ini file from local to docker container?
Similar to
FROM php:7.1-fpm
# Install system packages
RUN apt-get update && apt-get install -y \
openssl \
libssh2-1 \
libssh2-1-dev \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
RUN pecl install xdebug
# Enable php extensions
RUN docker-php-ext-install mysqli pdo_pgsql
RUN pecl install ssh2-1.1.2
# Copy custom php.ini file
ADD ./deployment/my.php.ini /usr/local/etc/php/

Categories