同福

使用Dockerfile搭建TFLinux的PHP+FPM+Nginx环境【20210528】

介绍

介绍

前面福哥已经教给大家使用Dockerfile安装各种服务器软件的方法了,今天福哥要带着大家把TFLinux服务器上的软件都转移到Docker容器里面。使用Docker容器搭建服务器环境是现如今部署服务器环境的主流方式,福哥顺应潮流将Docker这种部署方式教给大家,活到老学到老嘛~~

这次福哥整理的是PHP+FPM+Nginx环境,因为docker-compose不支持PHP+apache的组合,所以福哥不得不改用PHP+FPM组合搭建PHP环境了,PHP+FPM是不能单独提供web服务的,这里福哥使用Nginx作为web服务器软件。

FastCGI

PHP+FPM就是以FastCGI模式运行PHP的模式,FPM模式是以进程的方式运行PHP的,在早期的PHP时代进程运行PHP是一个很low的做法,大家更推崇线程方式运行PHP,作为Apache模块运行PHP一直是主流的运行PHP的方式。

直到PHP5.4开始,FastCGI模式运行PHP逐渐展露了头角,PHP-FPM解决了之前的诸如内存占用过多、进程过多等等问题,这使得PHP官方承认了FastCGI模式运行PHP,慢慢的这种方式也被广大PHPer们接收了。

PHP+FPM+Nginx的组合是一种“动静分离”的部署方式,PHP+FPM负责动态程序,Nginx负责静态页面。

PHP

直接部署

直接部署的方式采用的是PHP+Apache的组合,Apache是以模块方式运行PHP程序的,Apache会根据指定的扩展名调用PHP解析器对PHP程序进行解析执行,而非PHP程序的资源文件Apache会原汁原味地将其直接展示出来。

这种情况下,我们只需要安装PHP和Apache就可以了,项目也不需要区分PHP程序和资源文件。

Docker部署

通过PHP+FPM+Nginx的组合就需要把PHP程序的解析工作交给FPM来完成,而资源文件则交给Nginx来处理。

PHP+FPM是一个镜像,Nginx又是另外一个镜像,所以PHP+FPM+Nginx的组合就是两个镜像的配合运行的模式。

Dockerfile

因为PHP+FPM也会占用一个端口,后面的Nginx也会占用一个端口,为了避免端口冲突问题,福哥设计的端口分配规则如下:

  • PHP+FPM:tfphp(8168),tfums(8170)。

  • Nginx:默认(8080),tfphp(8068),tfums(8070)。

tfphp.conf

[tfphp]

user = www-data
group = www-data

listen = 8168

pm = dynamic
pm.max_children = 5
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 3

catch_workers_output = yes
access.log = /var/log/php/tfphp-access.log

tfums.conf

[tfums]

user = www-data
group = www-data

listen = 8170

pm = dynamic
pm.max_children = 5
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 3

catch_workers_output = yes
access.log = /var/log/php/tfums-access.log

Dockerfile

这里面福哥就是把tfphp.conf和tfums.conf导入到镜像里面了。

FROM php:7.4-fpm-buster

MAINTAINER Andy Bogate
MAINTAINER tongfu@tongfu.net
MAINTAINER https://tongfu.net/dockerfile
MAINTAINER 2021/5/26
MAINTAINER v1.0.0

EXPOSE 8168 8170

WORKDIR /tongfu.net/web

# local mirror
RUN sed -i 's/deb.debian.org/ftp.cn.debian.org/g' /etc/apt/sources.list \
&& sed -i 's/security.debian.org/ftp.cn.debian.org/g' /etc/apt/sources.list

# timezone
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo 'Asia/Shanghai' >/etc/timezone

# env
RUN apt-get update \
&& apt-get -y install wget libwebp-dev libjpeg-dev libpng-dev libfreetype6-dev libc-client-dev libkrb5-dev libzip-dev

# source extract
RUN docker-php-source extract

# package build
RUN mkdir /packages

# gd extension
RUN docker-php-ext-configure gd \
--with-jpeg=/usr/include \
--with-freetype=/usr/include/ \
&& docker-php-ext-install gd \
&& docker-php-ext-enable gd

# mysql extension
RUN docker-php-ext-install pdo_mysql \
&& docker-php-ext-enable pdo_mysql

# redis extension
RUN cd /packages \
&& wget http://pecl.php.net/get/redis-4.1.0.tgz \
&& tar -xzvf redis-4.1.0.tgz \
&& cd redis-4.1.0 \
&& /usr/local/bin/phpize \
&& ./configure --with-php-config=/usr/local/bin/php-config \
&& make && make install \
&& cd ../ \
&& docker-php-ext-enable redis

# imap extension
RUN docker-php-ext-configure imap \
--with-kerberos \
--with-imap-ssl \
&& docker-php-ext-install imap \
&& docker-php-ext-enable imap

# zlib extension
RUN mv /usr/src/php/ext/zlib/config0.m4 /usr/src/php/ext/zlib/config.m4 \
&& docker-php-ext-install zlib \
&& docker-php-ext-enable zlib

# mongodb extension
RUN cd /packages \
&& wget http://pecl.php.net/get/mongodb-1.7.4.tgz \
&& tar -xzvf mongodb-1.7.4.tgz \
&& cd mongodb-1.7.4 \
&& /usr/local/bin/phpize \
&& ./configure --with-php-config=/usr/local/bin/php-config \
&& make && make install \
&& cd ../ \
&& docker-php-ext-enable mongodb

# confiugure
RUN cd /usr/local/etc/php \
&& cp php.ini-production php.ini \
&& sed -i 's/display_errors\s*=.*/display_errors = Off/' php.ini \
&& sed -i 's/error_reporting\s*=.*/error_reporting = E_ALL \& ~E_NOTICE \& ~E_STRICT \& ~E_DEPRECATED/' php.ini \
&& sed -i 's/;error_log\s*=\s*php_errors\.log/error_log = \/var\/log\/php\/php_errors.log/' php.ini \
&& sed -i 's/;date\.timezone\s*=.*/date.timezone = Asia\/Shanghai/' php.ini

# package delete
RUN rm -rf /packages

# source delete
RUN docker-php-source delete

# config
RUN mkdir /var/log/php \
&& cd /usr/local/etc/ \
&& sed -i 's/;error_log\s*=.*/error_log = \/var\/log\/php\/php-fpm.log/' php-fpm.conf \
&& sed -i 's/;daemonize\s*=.*/daemonize = no/' php-fpm.conf \
&& rm -f php-fpm.d/docker.conf \
&& rm -f php-fpm.d/zz-docker.conf \
&& rm -f php-fpm.d/www.conf \
&& rm -f php-fpm.d/www.conf.default
ADD tfphp.conf /usr/local/etc/php-fpm.d/tfphp.conf
ADD tfums.conf /usr/local/etc/php-fpm.d/tfums.conf

Nginx

Dockerfile

要使用nginx去实现apache的rewrite功能还是挺复杂的,nginx配置语法不仅仅没有RewriteCond/RewriteRule的功能,而且nginx配置语法还不支持与(&&)或(||)的语法。

为了实现apache的rewrite功能,福哥建立了$conds辅助变量功能解决与(&&)或(||)的语法问题。

default.conf

server {
    listen       8080;
    listen  [::]:8080;
    server_name  localhost;

    location / {
        root   /tongfu.net/web;
        index  index.html index.htm;
    }
}

tfphp.conf

server {
    listen       8068;
    listen  [::]:8068;
    server_name  localhost;

    # WEB-INF is forbidden
    if ( $uri ~ ^\/WEB\-INF\/ ) {
        return 403;
    }

    # condition except extension
    set $conds "1";
    if ( $uri !~* \.(js|css|map|jpg|jpeg|pjpeg|png|gif|txt|ico)$ ) {
        set $conds "${conds}1";
    }

    # condition except ueditor
    if ( $uri !~ ^\/ue\/ ) {
        set $conds "${conds}1";
    }

    # condition except route func and server func
    if ( $uri !~ (TFRouteMap\.php|server\-status|server\-info)$ ) {
        set $conds "${conds}1";
    }

    # route map
    if ( $conds = "1111" ) {
        rewrite ^\/(.*)$  /TFRouteMap.php;
    }

    # all requests location to root
    location / {
        root   /tongfu.net/web/TFPHP;
        index  index.html index.htm;
    }

    # all requests of PHP script location to fastcgi
    location ~ \.php$ {
        client_body_buffer_size      1m;

        root           /tongfu.net/web/TFPHP;
        fastcgi_pass   10.16.1.1:8168;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

tfums.conf

server {
    listen       8070;
    listen  [::]:8070;
    server_name  localhost;

    # WEB-INF is forbidden
    if ( $uri ~ ^\/WEB\-INF\/ ) {
        return 403;
    }

    # condition except extension
    set $conds "1";
    if ( $uri !~* \.(js|css|map|jpg|jpeg|pjpeg|png|gif|txt|ico)$ ) {
        set $conds "${conds}1";
    }

    # condition except ueditor
    if ( $uri !~ ^\/ue\/ ) {
        set $conds "${conds}1";
    }

    # condition except route func and server func
    if ( $uri !~ (TFRouteMap\.php|server\-status|server\-info)$ ) {
        set $conds "${conds}1";
    }

    # route map
    if ( $conds = "1111" ) {
        rewrite ^\/(.*)$  /TFRouteMap.php;
    }

    # all requests location to root
    location / {
        root   /tongfu.net/web/TFUMS;
        index  index.html index.htm;
    }

    # all requests of PHP script location to fastcgi
    location ~ \.php$ {
        client_body_buffer_size      1m;

        root           /tongfu.net/web/TFUMS;
        fastcgi_pass   10.16.1.1:8170;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

Dockerfile

FROM nginx:1.20

MAINTAINER Andy Bogate
MAINTAINER tongfu@tongfu.net
MAINTAINER https://tongfu.net/dockerfile
MAINTAINER 2021/5/26
MAINTAINER v1.0.0

EXPOSE 8068 8070

# local mirror
RUN sed -i 's/deb.debian.org/ftp.cn.debian.org/g' /etc/apt/sources.list \
&& sed -i 's/security.debian.org/ftp.cn.debian.org/g' /etc/apt/sources.list

# timezone
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo 'Asia/Shanghai' >/etc/timezone

# config
RUN rm -f /var/log/nginx/access.log \
&& rm -f /var/log/nginx/error.log
ADD default.conf /etc/nginx/conf.d/default.conf
ADD tfphp.conf /etc/nginx/conf.d/tfphp.conf
ADD tfums.conf /etc/nginx/conf.d/tfums.conf

测试

创建镜像

PHP+FPM

docker build -f Dockerfile -t tflinux-php-fpm7.4 ./

PHP+Nginx

docker build -f Dockerfile -t tflinux-php-nginx7.4 ./

启动容器

启动PHP+FPM

docker run -tid \
--name tflinux-php-fpm7.4 \
-h tflinux-php-fpm7.4 \
-p 10.16.1.1:8168:8168 \
-p 10.16.1.1:8170:8170 \
-v /tongfu.net/web/TFPHP/:/tongfu.net/web/TFPHP/ \
-v /tongfu.net/web/TFUMS/:/tongfu.net/web/TFUMS/ \
tflinux-php-fpm7.4

启动PHP+Nginx

docker run -tid \
--name tflinux-php-nginx7.4 \
-h tflinux-php-nginx7.4 \
-p 10.16.1.1:8080:8080 \
-p 10.16.1.1:8068:8068 \
-p 10.16.1.1:8070:8070 \
-v /tongfu.net/web/TFPHP/:/tongfu.net/web/TFPHP/ \
-v /tongfu.net/web/TFUMS/:/tongfu.net/web/TFUMS/ \
tflinux-php-nginx7.4

测试

一起就绪了,打开浏览器看看吧~~

home/topic/2021/0527/13/a8f82ab1907ff6f52c254a44c759d033.pnghome/topic/2021/0527/13/60b301eb78b8ea73e4f1d609db4ccb17.png

home/topic/2021/0527/13/290cd1884095ea91d7ef47493af5284b.png

总结

今天福哥带着童鞋们将之前学习的使用Dockerfile搭建各种服务器软件的技巧综合了一下,使用这些技巧将我们的TFLinux服务器上面直接部署的PHP、Apache转移到了Docker里面,利用Docker的数据卷映射技术将我们的TFPHP、TFUMS项目的程序部署到了容器里面。

这一课的内容牵扯到的问题很多,福哥将在后面的课程里面一一给大家详细讲解!

使用PHP+FPM+Nginx的组合部署PHP运行环境和PHP+Apache的组合部署有一些区别,我们的TFPHP框架的路由模块需要针对新环境进行适配才能正常运行,下一课福哥将会针对这个问题给大家讲解一下,敬请期待~~