Docker - phpfpm镜像下的php扩展安装配置

php的容器内容基于php:alpine镜像安装

1. PHP核心库安装

  • docker-php-ext-configure:编译过程中,通过docker-php-ext-configure可以指定相关编程参数;
  • docker-php-ext-install:安装核心扩展,并enbale扩展到配置文件,或者通过指定目录安装第三方扩展;
  • docker-php-ext-enable:通过pecl安装的标准扩展后,需要通过enable加入到php.ini,extension扩展中(有的是基于单独ini扩展配置文件,单独放在conf.d下管理)
  • docker-php-source:轻松提取tar或删除提取的源,请务必将其删除在docker镜像的同一层中,这块用得不多
FROM php:7.2-cli
RUN docker-php-source extract \
    # do important things \
    && docker-php-source delete

2. 安装前的准备

php的扩展基于c来编写的,需要有对应的gcc编译环境,否则会遇到编译器缺失的错误

2.1. 编译器缺失

Alpine系统中的gcc编译环境安装

参考:

安装php扩展过程中报错,镜像选择的是php-apline镜像

/usr/local/etc # apk add build-base
(1/19) Installing binutils (2.30-r5)
(2/19) Installing libmagic (5.32-r0)
(3/19) Installing file (5.32-r0)
(4/19) Installing gmp (6.1.2-r1)
(5/19) Installing isl (0.18-r0)
(6/19) Installing libgomp (6.4.0-r9)
(7/19) Installing libatomic (6.4.0-r9)
(8/19) Installing pkgconf (1.5.3-r0)
(9/19) Installing libgcc (6.4.0-r9)
(10/19) Installing mpfr3 (3.1.5-r1)
(11/19) Installing mpc1 (1.0.3-r1)
(12/19) Installing libstdc++ (6.4.0-r9)
(13/19) Installing gcc (6.4.0-r9)
(14/19) Installing musl-dev (1.1.19-r10)
(15/19) Installing libc-dev (0.7.1-r0)
(16/19) Installing g++ (6.4.0-r9)
(17/19) Installing make (4.2.1-r2)
(18/19) Installing fortify-headers (0.9-r0)
(19/19) Installing build-base (0.5-r1)
Executing busybox-1.28.4-r1.trigger
OK: 177 MiB in 50 packages

2.2. 缺少autoconf

/usr/local/etc # apk add autoconf
(1/4) Installing m4 (1.4.18-r1)
(2/4) Installing libbz2 (1.0.6-r6)
(3/4) Installing perl (5.26.3-r0)
(4/4) Installing autoconf (2.69-r2)
Executing busybox-1.28.4-r1.trigger
OK: 216 MiB in 54 packages

3. PHP Core Extensions

php除了常见已经安装的扩展,可以通过php -m查看,对应的配置路径可以基于php-config查看,其余相关的扩展安装涉及:

php核心库包含在内置的PHP source包中,可以通过docker-php-ext-install直接安装,诸如opcache、sockets、curl、bcmath等

3.1. 核心库基于docker-php-ext-install命令安装

/usr/local/etc # docker-php-ext-install -h
usage: /usr/local/bin/docker-php-ext-install [-jN] ext-name [ext-name ...]
   ie: /usr/local/bin/docker-php-ext-install gd mysqli
       /usr/local/bin/docker-php-ext-install pdo pdo_mysql
       /usr/local/bin/docker-php-ext-install -j5 gd mbstring mysqli pdo pdo_mysql shmop

if custom ./configure arguments are necessary, see docker-php-ext-configure

Possible values for ext-name:
bcmath bz2 calendar ctype curl dba dom enchant exif fileinfo filter ftp gd gettext gmp hash iconv imap interbase intl json ldap mbstring mysqli oci8 odbc opcache pcntl pdo pdo_dblib pdo_firebird pdo_mysql pdo_oci pdo_odbc pdo_pgsql pdo_sqlite pgsql phar posix pspell readline recode reflection session shmop simplexml snmp soap sockets sodium spl standard sysvmsg sysvsem sysvshm tidy tokenizer wddx xml xmlreader xmlrpc xmlwriter xsl zend_test zip

3.2. 安装gd扩展

alpine与其他系统的包名有些许差别:https://github.com/docker-library/php/issues/225

// 在phpfpm容器内部
apk update && apk add \
    freetype-dev \
    libjpeg-turbo-dev \
    libpng-dev \
&& docker-php-ext-install -j$(nproc) iconv \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j$(nproc) gd

4. PECL extensions

PECL是PHP Extensions的存储库,提供了用于下载和开发PHP扩展的所有已知扩展和托管工具的目录,PECL使用的包装和分销系统与其姐妹PEAR共享。

4.1. PHP Extension Community Library

PECL代表PHP扩展社区库 - PHP Extension Community Library它具有用C编写的扩展,可以加载到PHP中以提供其他功能。您需要具有管理员权限,C编译器和相关工具链才能安装这些扩展。

4.2. PHP Extension and Application Repository

PEAR是PHP扩展和应用程序库 - PHP Extension and Application Repository它具有用PHP编写的库和代码,只需下载,安装并包含在您的代码中即可。(这块目前大都被composer包管理统一了,可以认为composer是pear安装程序的继承者)

4.3. PECL标准库基于pecl命令安装socks、redis、xdebug

因为是C扩展,注意提前安装好对应的gcc编译环境!

// 在phpfpm容器内部
pecl install redis \
    && docker-php-ext-enable redis xdebug

注意:强烈建议用户使用其明确的版本号pecl install的调用,以确保适当的PHP版本兼容性:

例如,memcached-2.2.0没有PHP版本约束(https://pecl.php.net/package/memcached/2.2.0),但memcached-3.0.4需要PHP 7.0.0或更新版本(https://pecl.php.net/package/memcached /3.0.4)。pecl install memcached在PHP 5.6上执行(没有特定版本)时,PECL将尝试安装最新版本并失败。

// 搜索对应的扩展,并加入版本
/usr/local/etc # pecl search redis

pecl install redis-4.3.0

5. 非核心库

某些扩展不通过Core或PECL提供; 这些也可以安装,但过程自动化程度较低,大致的流程:

  1. 通过curl下载对应的包
  2. 创建对应的目录
  3. 解压包到指定目录
  4. 编译安装
  5. 清理下载的包,以及安装过程中产生的中间信息,降低镜像包的大小
// 通过phpize解压,make安装后,再通过docker-php-ext-enable加入到ini配置文件中
cd /tmp \
    && curl -fsSL 'https://xcache.lighttpd.net/pub/Releases/3.2.0/xcache-3.2.0.tar.gz' -o xcache.tar.gz \
    && mkdir -p xcache \
    && tar -xf xcache.tar.gz -C xcache --strip-components=1 \
    && ( \
        cd xcache \
        && phpize \
        && ./configure --enable-xcache \
        && make -j "$(nproc)" \
        && make install \
    ) \
    && docker-php-ext-enable xcache \
    && rm -r xcache \    
    && rm xcache.tar.gz \

// 或者通过docker-php-ext-configure、docker-php-ext-install安装
cd /tmp \
    && curl -fsSL 'https://xcache.lighttpd.net/pub/Releases/3.2.0/xcache-3.2.0.tar.gz' -o xcache.tar.gz \
    && mkdir -p /tmp/xcache \
    && tar -xf xcache.tar.gz -C /tmp/xcache --strip-components=1 \
    && docker-php-ext-configure /tmp/xcache --enable-xcache \
    && docker-php-ext-install /tmp/xcache \
    && rm -r /tmp/xcache \
    && rm xcache.tar.gz

6. Dockerfile - 完整版本

以上都是基于容器内部安装的,我们可以把上述内容,提取出来,放入Dockerfile内部,做成自己的php环境镜像包,以便后续引入,避免重复执行下载、编译、安装的流程!

  1. 将容器中的php.ini复制出来
  2. 修改php.ini以及基于自己需要安装的扩展,撰写对应的Dockerfile
  3. 可以通过将配置文件复制到$PHP_INI_DIR/conf.d/目录中来自定义默认配置
  4. 其他类似的php配置可以基于COPY或者RUN编辑修改
  5. 注意:这里适当RUN分开了,没有遵循最佳实践,为了更清晰表述
    # phpfpm Dockerfile
    FROM php:7.3-alpine

    # php扩展安装
    RUN apk update && apk add build-base autoconf\
        && pecl install xdebug redis \
        && docker-php-ext-enable redis xdebug \
        && docker-php-ext-install sockets

    # gb扩展
    RUN apk update && apk add \
        freetype-dev \
        libjpeg-turbo-dev \
        libpng-dev \
    && docker-php-ext-install -j$(nproc) iconv \
    && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install -j$(nproc) gd

    # xdebug配置,macOS下的remote需要通过特殊的dns `host.docker.internal`解析
    RUN sed -i '$a \
    xdebug.collect_vars=on\n\
    xdebug.collect_params=4\n\
    xdebug.remote_autostart=on\n\
    xdebug.idekey=phpstorm\n\
    xdebug.remote_enable=on\n\
    xdebug.remote_host=host.docker.internal\n\
    xdebug.remote_port=9801\n\
    ' $PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini

    # php.ini设置
    WORKDIR /usr/local/etc/
    COPY ./php.ini $PHP_INI_DIR/php.ini

7. PHP-FPM进程信号操作

SIGINT,SIGTERM: immediate termination
SIGQUIT: graceful stop
SIGUSR1: re-open log file
SIGUSR2: graceful reload of all workers + reload of fpm conf/binary

8. 参考