在实际的项目部署中,我们有时候会遇到在一个服务器上部署多个 php 环境的情况。遇到这种情况,我们可以在同一物理机上装多个 php-fpm 监听不同端口,Nginx 根据不同的 Vhost 去找不同的 php-fpm 解析。

上述方法虽然可以,但是在项目管理上并不是很友好,比如我需要在某个项目执行 PHP 脚本,那还需要写 /path/php script.php 这样的话就需要每个维护项目的人都十分清楚,哪个项目应该用哪个版本的 PHP 去执行相应的脚本。

其次,如果某天需要把某个项目迁移到其他服务器了,我们还需要在新机器上安装 PHP 环境。

如果用 docker 进行部署,就不会有上面的问题,我们只需要写一次 Dockfile 可以在任何服务器上构建出相同的 php-fpm 环境,从而让迁移更简单,如果需要执行脚本,只需要进入对应的容器,直接执行 php script.php 即可。

image.png

php-fpm 官方镜像介绍

php Tags | Docker Hub 找到你所需的基础镜像的 tag

image.png

扩展安装

Docker PHP 安装有三种方式

Core Extensions:

FROM php:8.2-fpm
RUN apt-get update && apt-get install -y \
libfreetype-dev \
libjpeg62-turbo-dev \
libpng-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd

PECL extensions :

FROM php:8.2-cli
RUN pecl install redis-5.3.7 \
&& pecl install xdebug-3.2.1 \
&& docker-php-ext-enable redis xdebug

手动编译安装:

FROM php:8.2-cli
RUN curl -fsSL '[url-to-custom-php-module]' -o module-name.tar.gz \
&& mkdir -p module-name \
&& sha256sum -c "[shasum-value] module-name.tar.gz" \
&& tar -xf module-name.tar.gz -C module-name --strip-components=1 \
&& rm module-name.tar.gz \
&& ( \
cd module-name \
&& phpize \
&& ./configure --enable-module-name \
&& make -j "$(nproc)" \
&& make install \
) \
&& rm -r module-name \
&& docker-php-ext-enable module-name

php 配置文件介绍

如果你需要修改或新增 php 的配置,可以在 /usr/local/etc/php/conf.d/ 里建立对应的配置文件,然后把配置写在里面重启容器即可。

比如我想覆盖 php-fpm 对于上传文件的限制,就可以按照下面的脚本来实现。

echo "file_uploads = On" >> /usr/local/etc/php/conf.d/uploads.ini \
&& echo "memory_limit = 64M" >> /usr/local/etc/php/conf.d/uploads.ini \
&& echo "upload_max_filesize = 64M" >> /usr/local/etc/php/conf.d/uploads.ini

Dockerfile

FROM php:7.3.8-fpm  
RUN cd /tmp \  
    && php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" \  
    && php composer-setup.php \  
    && php -r "unlink('composer-setup.php');" \  
    && mv composer.phar /bin/composer \  
    && composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ \  
    && composer clear  
RUN echo " " > /etc/apt/sources.list \  
    && echo "deb http://mirrors.aliyun.com/debian buster main" >> /etc/apt/sources.list \  
    && echo "deb http://mirrors.aliyun.com/debian-security buster/updates main" >> /etc/apt/sources.list \  
    && echo "deb http://mirrors.aliyun.com/debian buster-updates main" >> /etc/apt/sources.list \  
    && echo "file_uploads = On" >> /usr/local/etc/php/conf.d/uploads.ini \  
    && echo "memory_limit = 64M" >> /usr/local/etc/php/conf.d/uploads.ini \  
    && echo "upload_max_filesize = 64M" >> /usr/local/etc/php/conf.d/uploads.ini \  
    && echo "post_max_size = 64M" >> /usr/local/etc/php/conf.d/uploads.ini \  
    && echo "max_execution_time = 600" >> /usr/local/etc/php/conf.d/uploads.ini \  
    && apt-get update  \  
    && apt-get install -y --no-install-recommends git vim libpng-dev libjpeg-dev libfreetype6-dev \  
    && apt-get clean \  
    && rm -rf /var/lib/apt/lists/*  

Run pecl install redis \  
    && docker-php-ext-enable redis \  
    && docker-php-ext-install mysqli \  
    && docker-php-ext-install pdo_mysql bcmath\  
    && docker-php-ext-configure gd --enable-gd-native-ttf --with-freetype-dir=DIR --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ && docker-php-ext-install gd  

WORKDIR /var/www  


EXPOSE 9000  
CMD ["php-fpm"]

上述 Dockerfile 基于 php:7.3.8-fpm 安装了所需扩展

构建镜像

docker build -t php73 .

启动镜像

docker run -p 9001:9000 -d --name php-fpm73 -v /path/to/project:/opt/www -it php73

配置 Nginx

...
# 配置 php 文件解析
location ~ [^/]\.php(/|$)
{
    fastcgi_index index.php;
    fastcgi_pass 127.0.0.1:9001;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME /var/www/$fastcgi_script_name;
    fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}
...

systemctl reload nginx 重载 nginx 使配置生效。

到此就完成了使用 docker php-fpm 去解析 PHP 对应的脚本了。