关于PHP-FPM与文件系统、Apache及源码文件关系的技术咨询
嘿,我来帮你把这里面的逻辑理清楚——你这种遗留PHP 5.6系统迁移到Docker的场景,我之前也帮朋友处理过,确实容易在PHP-FPM和文件系统的关系上犯迷糊。
首先得戳破一个关键误区:PHP-FPM绝对不是纯网络应用,它必须能直接访问你的PHP源码文件才能工作。接下来我一步步给你拆解整个交互流程,以及你Docker场景下需要注意的点:
Apache与PHP-FPM的核心交互逻辑
当用户请求一个PHP文件时,整个流程是这样的:
- 浏览器发请求到Apache,比如
yourdomain.com/old-app/index.php - Apache根据配置(比如
mod_proxy_fcgi或者mod_fastcgi的规则)判断这是PHP文件,需要交给PHP-FPM处理 - Apache通过FastCGI协议(可以是TCP端口或者Unix套接字)把请求信息传给PHP-FPM,这里面最关键的参数是该PHP文件在服务器上的绝对路径(比如
/var/www/old-app/index.php) - PHP-FPM收到请求后,会根据这个路径去文件系统里读取对应的PHP文件,解析执行,生成输出内容
- PHP-FPM再把执行结果通过FastCGI协议回传给Apache,最后由Apache把内容返回给浏览器
从这个流程就能看出来:PHP-FPM根本不会从Apache那里接收文件内容,它只会拿到文件路径,然后自己去读文件。所以如果PHP-FPM所在的环境(你的Docker容器)找不到这个路径对应的文件,直接就会报错。
你的Docker容器场景该怎么处理?
既然PHP-FPM容器必须访问源码,那有两种常用方案:
- 挂载共享源码:用Docker的
bind mount或者volume,把主机上(或者Apache所在环境)的源码目录挂载到PHP-FPM容器的对应路径下。比如Apache这边的网站根目录是/var/www/old-app,那你启动PHP-FPM容器时就要加参数:docker run -v /var/www/old-app:/var/www/old-app ...,这样容器里的/var/www/old-app和主机上的目录完全同步,Apache传过来的路径在容器里是有效的。 - 把源码打包进镜像:如果你的遗留系统源码变动很少,也可以直接把源码复制到PHP-FPM镜像里(在Dockerfile里加
COPY ./old-app /var/www/old-app)。这种方式的好处是容器自带源码,部署方便,但缺点是每次改源码都要重新构建镜像。
针对你几个具体问题的解答
PHP-FPM是不是纯网络应用?
完全不是。它必须依赖文件系统里的PHP源码才能执行请求,你没法把它放在一个完全没有源码的机器上运行——那样它收到Apache传的路径后,找不到文件,会直接返回500错误。容器里的PHP-FPM文件系统需要关心吗?
当然要!核心是要保证Apache传递的文件绝对路径,在PHP-FPM容器里是存在且可访问的。举个反例:如果Apache里的文件路径是/home/user/old-app/index.php,但容器里你把源码放在/var/www/html,那PHP-FPM收到/home/user/old-app/index.php这个路径后,根本找不到文件,直接报错。关于数据库连接
你提到容器能访问MySQL和Mongo,这个没问题——只要Docker网络配置正确(比如把容器加入和数据库同个网络,或者数据库端口映射到主机),PHP代码里的数据库连接地址配置正确就行,这部分和文件系统的逻辑是完全独立的。
额外小建议
你现在用主机上的Apache对接容器里的PHP-FPM是可行的,只需要把PHP-FPM容器的9000端口(默认端口)映射到主机,然后在Apache的配置里指定FastCGI的目标地址,比如用ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/var/www/old-app/$1这样的规则,同时确保源码挂载路径一致就好。
备注:内容来源于stack exchange,提问作者David Newcomb

