首页 > 解决方案 > 502 Bad Gateway - Google Cloud 在冷启动时使用 php-fpm(未找到套接字)运行

问题描述

我正在处理一个问题,即对我的 Google Cloud Run 容器的第一个请求导致 502 Bad Gateway 错误。在日志中可以看到以下内容:

[crit] 23#23: *3 connect() to unix:/run/php/php7.4-fpm.sock failed (2: No such file or directory) while connecting to upstream, client: 169.254.8.129, server: domain.com, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.4-fpm.sock:", host: "my.domain.com"

但是,在第二个请求上它工作正常。

我将 supervisord 与 php-fpm 和 nginx 一起使用。

Dockerfile

FROM php:7.4-fpm

ENV COMPOSER_MEMORY_LIMIT='-1'

RUN apt-get update && \
    apt-get install -y --force-yes --no-install-recommends \
        nginx \
        supervisor \
        libmemcached-dev \
        libzip-dev \
        libz-dev \
        libzip-dev \
        libpq-dev \
        libjpeg-dev \
        libpng-dev \
        libfreetype6-dev \
        libssl-dev \
        openssh-server \
        libmagickwand-dev \
        git \
        cron \
        nano \
        libxml2-dev \
        libreadline-dev \
        libgmp-dev \
        mariadb-client \
        unzip

RUN docker-php-ext-install exif zip pdo_mysql intl

#####################################
# PHPRedis:
#####################################
RUN pecl install redis && docker-php-ext-enable redis

#####################################
# Imagick:
#####################################

RUN pecl install imagick && \
    docker-php-ext-enable imagick

#####################################
# PHP Memcached:
#####################################

# Install the php memcached extension
RUN pecl install memcached && docker-php-ext-enable memcached

#####################################
# Composer:
#####################################

# Install composer and add its bin to the PATH.
RUN curl -s http://getcomposer.org/installer | php && \
    echo "export PATH=${PATH}:/var/www/vendor/bin" >> ~/.bashrc && \
    mv composer.phar /usr/local/bin/composer
# Source the bash
RUN . ~/.bashrc

#####################################
# Laravel Schedule Cron Job:
#####################################

# RUN echo "* * * * * www-data /usr/local/bin/php /var/www/artisan schedule:run >> /dev/null 2>&1"  >> /etc/cron.d/laravel-scheduler
# RUN chmod 0644 /etc/cron.d/laravel-scheduler

#
#--------------------------------------------------------------------------
# NGINX
#--------------------------------------------------------------------------
#

RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log

ADD infrastructure/nginx/nginx.conf /etc/nginx/sites-available/default
ADD infrastructure/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf

#
#--------------------------------------------------------------------------
# Move config files
#--------------------------------------------------------------------------
#

ADD ./infrastructure/php/php.ini /usr/local/etc/php/conf.d/php.ini
ADD ./infrastructure/php/php-fpm.conf /usr/local/etc/php-fpm.d/zz-docker.conf

#
#--------------------------------------------------------------------------
# Ensure fpm socket folder is present
#--------------------------------------------------------------------------
#


RUN mkdir -p /run/php/


RUN rm -r /var/lib/apt/lists/*

RUN usermod -u 1000 www-data

COPY ./infrastructure/entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/entrypoint.sh
RUN ln -s /usr/local/bin/entrypoint.sh /
ENTRYPOINT ["entrypoint.sh"]

WORKDIR /var/www
COPY . .
RUN chown -R www-data:www-data /var/www
RUN composer install

EXPOSE 8000

入口点.sh

#!/bin/bash

# Start the cron service.
service cron start

##
# Run artisan migrate
##

php artisan migrate

##
# Run a command or start supervisord
##

if [ $# -gt 0 ];then
    # If we passed a command, run it
    exec "$@"
else
    # Otherwise start supervisord
    /usr/bin/supervisord
fi

Nginx.conf

server {
    listen 8000 default_server;

    root /var/www/public;

    index index.html index.htm index.php;

    server_name my.domain.com;

    charset utf-8;

    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt  { log_not_found off; access_log off; }

    # Remove index.php$
    if ($request_uri ~* "^(.*/)index\.php/*(.*)") {
        return 301 $1$2;
    }

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;
        fastcgi_buffering off;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    error_page 404 /index.php;
}

phpfpm 自定义配置

[global]
daemonize = no

[www]
listen = /run/php/php7.4-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

监督者

[supervisord]
nodaemon=true
user=root

[program:nginx]
command=nginx -g "daemon off;"
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:php-fpm]
command=php-fpm
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

标签: phplaravelnginxgoogle-cloud-runfpm

解决方案


冷启动的 Cloud Run 容器需要执行多项任务,然后才能根据文档处理请求。这可能是第一个请求失败的原因,而后续请求得到了正确处理:

启动例程包括:启动服务、启动容器、运行 entrypoint 命令启动服务器、检查开放的服务端口

同一文档页面提供了一些技巧来避免冷启动和提高容器启动性能,特别是设置一些始终处于空闲状态的最小实例。由于 Cloud Run 可以缩减到 0 个实例,这将在没有活动实例时创建冷启动。

nginx.conf至于日志中的具体错误消息,根据此相关线程,您的文件中的路径似乎可能是错误的。根据线程,路径fpm应该是:

fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; //with your specific fpm version

推荐阅读