背景介绍
由于项目需要使用最新的apache web服务器软件,而docker镜像中的apache2.7 + php7整合镜像中的apache版本又较老,且考虑到编译安装的繁琐性,故最近进行了一次在docker下基于官方 httpd 和 php 镜像的web服务环境部署实验。
准备工作
首先,从docker官方源拉取httpd和php镜像。
sudo docker pull httpd
sudo docker pull php:7.0-fpm
sudo docker pull php:7.0-fpm
接着为web应用代码和容器配置文件创建目录
sudo mkdir /data/www # 存放web应用代码
sudo mkdir /data/config # 存放容器相关配置文件
sudo mkdir /data/logs # 存放相关日志文件
sudo mkdir /data/config/apache2 # 存放httpd容器配置文件
sudo mkdir /data/config/php-fpm # 存放php容器配置文件
sudo mkdir /data/logs/php-fpm # 存放php容器日志
运行容器
sudo docker run –name my-httpd -v /data/www/:/usr/local/apache2/htdocs -v /data/conf/apache2/:/usr/local/apache2/conf:ro -p 80:80 -d httpd
【命令解释】后台运行一个名为my-httpd的httpd容器,并挂载主机 /data/www 目录到容器的 /usr/local/apache2/htdocs 目录下作为web应用代码目录,以只读方式挂载主机 /data/config/apache2/ 目录到容器 /usr/local/apache2/conf 目录下,映射主机80端口到容器80端口。
sudo docker run –name my-phpfpm -p 9000:9000 -v /data/www/:/www -v /data/config/php-fpm:/usr/local/etc/php -v /data/logs/php-fpm/:/phplogs -d php:7.0-fpm
【命令解释】后台运行一个名为my-phpfpm的php:7.0-fpm容器,并挂载主机 /data/www 目录到容器的 /www 目录下作为web应用代码目录,以挂载主机 /data/config/php-fpm 到容器的 /usr/local/etc/php 目录下作为容器配置文件目录,以只读方式挂载 /data/logs/php-fpm 目录到容器的 /phplogs 目录下作为日志目录,映射主机9000端口到容器9000端口。
容器配置
修改httpd容器配置文件httpd.conf的第140、144行去掉前面的#号,以启用mod_proxy、mod_proxy_fcgi扩展。
修改httpd容器配置文件httpd.conf的第296行,增加对index.php等.php后缀文件的索引支持。
在httpd容器配置文件httpd.conf的末尾,增加以下配置项以转发php文件给php-fpm容器进行解析。
ProxyPassMatch ^/(.+\.php(/.)?)$ fcgi://172.17.0.1:9000/www/$1
172.17.0.1为主机在docker虚拟网络中的IP地址,9000为 php-fpm 容器映射到主机的端口号。此处不建议直接使用php-fpm容器的docker虚拟网络IP地址,因为容器重启时可能导致IP地址的变化。
此处使用的是请求文件名的正则匹配传递,需要注意的是在fcgi传递的文件名称前应加上实际文件在 php-fpm 容器中的绝对路径,如此处的 /www/$1 代表位于 php-fpm 容器中 /www 内的名为前面正则表达式匹配到的文件名称的引用。
异常处理
此时访问存放在主机 /data/www 目录中的 .php 文件可能会发现 php-fpm 服务报“file not found”错误,根据网友提供的经验,通常是由于运行 httpd 容器与 php-fpm容器的用户不同而产生的权限问题。可使用 ps -aux 命令看到,在进程列表中,httpd进程使用 daemon 用户运行,而 php-fpm 进程使用 www-data 用户运行。因此解决此问题需要统一二者的运行用户。
因为关于php-fpm进程的配置文件未被映射到主机,所以将相关配置文件复制到主机编辑后再拷贝回容器覆盖。或者直接进入容器安装vim编辑相关配置文件。
使用如下命令复制fpm相关配置文件到主机:
sudo docker cp my-phpfpm:/usr/local/etc/php-fpm.conf ~
sudo docker cp my-phpfpm:/usr/local/etc/php-fpm.d ~
【命令解释】复制my-phpfpm容器中的 /usr/local/etc/php-fpm.conf 、 /usr/local/etc/php-fpm.d 到当前用户家目录~。
查看php-fpm.conf文件,发现其中并无与运行用户相关的配置,但其引入了 /usr/local/etc/php-fpm.d 目录下的所有.conf配置文件。因此在 php-fpm.d 目录下找到 www.conf 并进行编辑。
修改www.conf第23、24行的user、group配置项为与httpd进程一致的 daemon 。最后覆盖配置文件到容器。
sudo docker cp ~/php-fpm.d/www.conf my-phpfpm:/usr/local/etc/php-fpm.d
【命令解释】复制当前用户家目录下的 php-fpm.d 目录中的 www.conf 文件到 my-phpfpm 容器中的 /usr/local/etc/php-fpm.d 目录以覆盖原文件。


