1

I am dealing with an issue where the first request towards my Google Cloud Run container results in a 502 Bad Gateway error. The following can be seen in the logs:

[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"

However, on the second request it works fine.

I am using supervisord together with php-fpm and 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

entrypoint.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 custom config

[global]
daemonize = no

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

supervisord

[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
FooBar
  • 5,752
  • 10
  • 44
  • 93
  • Show how the container is configured and built. Also try changing the socket to **/var/run/php/php7.4-fpm.sock** To confirm, build the container locally, exec into the container, and find the correct socket file path. – John Hanley Nov 08 '21 at 19:36
  • @JohnHanley It works fine locally when I run the container. It's only on google cloud run. However, I will update the answer with more data on how the container is built. – FooBar Nov 08 '21 at 20:50
  • Is your container responding (listening) on $PORT which defaults to 8080? Check your Nginx configuration. – John Hanley Nov 08 '21 at 20:52
  • @JohnHanley I just updated my question with dockerfile – FooBar Nov 08 '21 at 20:53
  • Also @JohnHanley it only seems to happen on the first request, i.e. when the Cloud Run is cold started. On requests coming thereafter, it works fine. – FooBar Nov 08 '21 at 20:58
  • Include the deploy command. Your container is listening on port 8000 which must be specified when deploying the container. Please fix the formatting for **phpfpm custom config** – John Hanley Nov 08 '21 at 21:13
  • Since your application works on the second request, you probably have a race condition. Keep in mind that all the supervisord structure is not necessary. Cloud Run is a Request/Response system. Launching services at each request just slows everything down. They are CPU idled after the response, which means those processes eventually timeout or die. – John Hanley Nov 08 '21 at 21:16
  • @JohnHanley oh, missed that. I've added formatting now. However, there's no such deploy command. What I've provided is basically everything. And yes, I was hoping for a way to avoid Supervisor for the exact reason you say. However, I'd prefer nginx. But using supervisor is the only way I see to have both running in one container. Otherwise I could fallback to apache I guess. – FooBar Nov 08 '21 at 22:23

1 Answers1

1

Cloud Run containers being cold started will need to perform several tasks before being able to serve requests according to the documentation. This could be the cause of the first request failing, while subsequent requests are served correctly:

The startup routine consists of: starting the service, starting the container, running the entrypoint command to start your server, checking for the open service port

The same documentation page offers several tips to avoid cold starts and improve container startup performance, specially, setting a number of minimum instances that are always idle. Since Cloud Run can scale down to 0 instances, this will create cold starts when there are no instances active.

As for the specific error message from the logs, it seems that a path from your nginx.conf file might be wrong according to this related thread. According to the thread, the path to fpm should be:

fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; //with your specific fpm version
ErnestoC
  • 2,660
  • 1
  • 6
  • 19
  • 1
    Was this information useful for your issue? In case it can help future users having the same error. – ErnestoC Nov 12 '21 at 00:24