用kubernetes中的php-fpm配置NGINX和“找不到文件”。错误
#php #docker #kubernetes #nginx

对于大学课程,我想设置两个不同的容器:

  • 应该使用PHP-FPM运行PHP应用程序
  • 另一个应该运行nginx

这听起来很容易,但是不幸的是,我花了很多时间才能使这个工作。主要是因为我不能
在Internet上找到足够的信息。最大的问题是如何为Nginx设置FastCGI,以便它
将请求正确传递到运行php-fpm的容器。

,但让我从Docker图像本身的设置开始。我已经有一个使用Symfony编写的申请,并且
存储库在项目目录的根目录中包含一个Dockerfile

FROM php:8.2-fpm
WORKDIR /var/www
RUN apt-get update
RUN apt-get install -y libpq-dev libzip-dev zip zlib1g-dev
RUN docker-php-ext-install pdo_pgsql
RUN docker-php-ext-install zip
RUN pecl install redis-5.3.7 && docker-php-ext-enable redis
COPY --from=composer /usr/bin/composer /usr/bin/composer
COPY . .
RUN composer install

这可能不是完美的,我可能仍然会使用它遇到东西,但是由于这不是本文的重点i
我只是要忽略那部分。为了构建Docker映像并将其推到注册表,我执行了以下
命令(我只与某些占位符一起在此博客文章中发布):

docker build -t <project-name> .
docker tag <project-name> <username>/<project-name>
docker push <username>/<project-name>

之后,我创建了一个YAML文件来描述Kubernetes
deployment
。由于我正在构建的软件
是关于管理某件事,我称此文件为administration.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
    name: administration-deployment
spec:
    replicas: 1
    selector:
        matchLabels:
            app: administration
    template:
        metadata:
            labels:
                app: administration
        spec:
            containers:
                - name: administration
                  image: <username>/<project-name>:latest
                  envFrom:
                      - secretRef:
                            name: administration

这足以使我的Docker图像使用PHP-FPM运行。但是,仍然缺少Web服务器。因此我
想要创建运行NGINX Web服务器的Kubernetes部署。我在
中存储以下YAML配置 nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
    name: nginx-deployment
spec:
    replicas: 1
    selector:
        matchLabels:
            app: nginx
    template:
        metadata:
            labels:
                app: nginx
        spec:
            containers:
                - name: nginx
                  image: nginx:1.24
                  volumeMounts:
                      - name: nginx-configmap
                        mountPath: /etc/nginx/conf.d
            volumes:
                - name: nginx-configmap
                  configMap:
                      name: nginx-configmap

这启动了一个Nginx Web服务器容器,然后将ConfigMap映射到
的容器的文件系统 /etc/nginx/conf.d,恰好是Nginx配置文件的文件夹。现在,要获得这一点的关键部分
设置工作:ConfigMap安装在上一个文件中:

apiVersion: v1
kind: ConfigMap
metadata:
    name: nginx-configmap
data:
    default.conf: |
        server {
            location / {
                try_files $uri /index.php$is_args$args;
            }

            location ~ ^/index\.php(/|$) {
                fastcgi_split_path_info ^(.+\.php)(/.*)$;

                fastcgi_pass administration-service:9000;
                fastcgi_param SCRIPT_FILENAME /var/www/public/index.php;
                fastcgi_param REQUEST_METHOD $request_method;
                fastcgi_param REQUEST_URI $request_uri;

                internal;
            }

            location ~ \.php$ {
                return 404;
            }
        }

关键部分将正确的SCRIPT_FILENAME设置为fastcgi_param,问题是我几乎找不到
有关此信息的任何信息(这激发了我写这篇博客文章)。我看了看
examples I found on the nginx website,但
它们似乎都没有在另一个容器中运行NGINX和PHP-FPM。包括默认配置文件
带有许多分布的fastcgi_params无效。 问题是他们设置了SCRIPT_FILENAME
对于$document_root$fastcgi_script_name$documentRoot是Nginx机器中的一条路径,但在PHP-FPM中
容器还有另一个文件夹结构。
这使PHP-FPM容器总是用页面响应“文件
找不到。”,而且由于它甚至没有说出哪个文件,所以很难调试。

我确定有不同的方法可以解决它,例如通过镜像两个容器中的文件夹结构,但我发现它
更容易(也更清洁)只需调整fastci_param SCRIPT_FILENAME,然后将其设置为
的绝对路径 php-fpm容器上的Symfony应用程序的public/index.php文件

所以所有要做的就是执行kubectl apply -f <directory>命令并享受一个工作的符号应用程序。