前言
为了配合nginx食用风味更佳,减少磁盘空间占用,笔者选择了fpm-alpine系列标签的镜像,但 Docker Hub 中 WordPress 项目的说明只介绍了latest标签(同apache标签)的镜像用法,其中并未涵盖fpm-alpine的用法。为此,笔者在这里做了小小的总结。
笔者选用的 WordPress 镜像标签为php7.4-fpm-alpine,这个标签下的镜像是以php:7.4-fpm-alpine为基础构建出来的。
Docker Compose
首先,以下面这个docker-compose.yml文件为例,运行一个 WordPress 实例。
version: '3.1'
services:
wordpress:
image: wordpress:php7.4-fpm-alpine
restart: always
ports:
- 9000:9000
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: dbuser
WORDPRESS_DB_PASSWORD: mansworldismutable
WORDPRESS_DB_NAME: dbname
WORDPRESS_TABLE_PREFIX: jinkan_
volumes:
- /somewhere/wordpress:/var/www/html
db:
image: mariadb
restart: always
environment:
MYSQL_DATABASE: dbname
MYSQL_USER: dbuser
MYSQL_PASSWORD: mansworldismutable
MYSQL_RANDOM_ROOT_PASSWORD: seasbecomemulberryfields
volumes:
- db:/var/lib/mysql
volumes:
db:
PHP-FPM 配置
在运行该镜像的容器实例后,通过docker exec -ti <WordPress容器名称>/bin/sh进入容器的 Shell,查看 PHP-FPM 的配置。
在/usr/local/etc/php-fpm.conf文件的最后一行,可以看到下面这行配置。
include=etc/php-fpm.d/*.conf
即 PHP-FPM 配置中会自动包含/usr/local/etc/php-fpm.d目录下所有以.conf结尾文件的内容。镜像中该目录下包含 3 个.conf文件:docker.conf、www.conf和zz-docker.conf,其中有两个文件需要特别关注。
一是www.conf中配置了一个名为www的 PHP-FPM 进程池,运行进程的用户和组均为www-data。用id命令可以看出,www-data的 UID 为 82。
$ id www-data
uid=82(www-data) gid=82(www-data) groups=82(www-data),82(www-data)
因此,如果需要修改 WordPress 中的文件,就需要按上述 UID 配置/somewhere/wordpress中的相应目录或文件的写权限。
二是zz-docker.conf中指定了www进程池监听 9000 端口,与 Dockerfile 中EXPOSE语句对应。
[www]
listen = 9000
那么,之后配置 Nginx 反向代理就要指向这个端口。
Nginx 配置
这一步,先与大多数 LNMP 套件配置一样,通过 FastCGI 连接到 PHP-FPM,让 Nginx 作为反向代理。在 Nginx 的配置中添加一个upstream节,把 WordPress 容器的 9000 端口作为上游。
upstream wordpress {
server 127.0.0.1:9000;
}
修改server节的根目录为/somewhere/wordpress。
server {
<...>
root /somewhere/wordpress;
}
然后在server节中做如下配置,匹配 WordPress 的 URL 重写机制,让 Nginx 直接提供静态文件,并代理 URL 以.php结尾的请求,提供给作为上游的 PHP-FPM。
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass wordpress;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
大多时候 LNMP 套件中的 PHP-FPM 和 Nginx 都安装在同一台机器上,所以都会配置 FastCGI 参数SCRIPT_FILENAME为$document_root$fastcgi_script_name,即让 PHP-FPM 以server节中配置的root为根目录。此时,以http://example.com/index.php为例,则会让作为上游的 PHP-FPM 执行/somewhere/wordpress/index.php文件,会在 Nginx 日志中得到这样的错误。
2020/10/11 17:00:14 [error] 101982#101982: *17 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 42.42.42.42, server: example.com, request: "GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "example.com"
这是因为 WordPress 镜像中,WordPress 代码根目录实际位于/var/www/html,也是 PHP-FPM 需要访问的根目录,而镜像中/somewhere/wordpress并不存在。因此,需要修改该参数为如下。
location ~ \.php$ {
<...>
fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
}
然后,就没有然后了。