
Cloud Run의 단일 컨테이너에서 Nginx+PHP-FPM을 실행하는 데 문제가 있습니다. 내 컨테이너는 Alpine을 기반으로 하며 Supervisor를 통해 Nginx 및 PHP-FPM 시작을 관리합니다. 전반적으로 잘 작동하지만 Nginx가 HTTP 포트 수신을 시작하는 시점과 PHP-FPM 스핀업 사이에 짧은 시간 간격이 있습니다. 이로 인해 다음 로그 메시지와 함께 502 HTTP 오류가 나타납니다.
6#6: *3 connect() failed (111: Connection refused) while connecting to upstream, client: 169.254.8.129, server: _, request: "POST / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000"
여기서 문제는 Cloud Run이 8080 포트를 열 때 컨테이너가 요청을 처리할 준비가 되었다고 판단한다는 것입니다. 포트가 열린 직후 Cloud Run은 FPM이 아직 준비되지 않았기 때문에 첫 번째 시도에서 항상 실패하는 요청을 보냅니다. NOTICE: fpm is running, pid 4
첫 번째 요청이 도착하고 실패한 후에 로그 메시지가 나타납니다.
PHP-FPM이 준비된 경우에만 포트를 열도록 Nginx를 관리하는 방법은 무엇입니까?
감독자 구성:
[supervisord]
nodaemon=true
logfile=/dev/null
logfile_maxbytes=0
pidfile=/run/supervisord.pid
[program:php-fpm]
command=php-fpm -F
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=false
startretries=0
[program:nginx]
command=nginx -g 'daemon off;'
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=false
startretries=0
Nginx 구성:
# Write temporary files to /tmp so they can be created as a non-privileged user
client_body_temp_path /tmp/client_temp;
proxy_temp_path /tmp/proxy_temp_path;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
access_log /dev/stdout;
error_log /dev/stderr notice;
server {
listen 8080 default_server;
index index.php;
keepalive_requests 10;
keepalive_timeout 60 60;
root /var/www/html/app/public;
charset utf-8;
server_name _;
# Deny hidden files (.htaccess, .htpasswd, .DS_Store).
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
########################
# mappings #
########################
location ~ \.(js|css|png|jpg|ico) {
expires 5d;
try_files $uri $uri/ =404;
return 404;
}
# Allow fpm ping and status from localhost
location ~ ^/(fpm-status|fpm-ping)$ {
access_log off;
allow 127.0.0.1;
deny all;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
}
location / {
client_max_body_size 100m;
try_files $uri @fpm;
}
location @fpm {
# worker may take long time to finish (max 1 hour)
fastcgi_read_timeout 3600s;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param HTTP_PROXY "";
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html/app/public/index.php;
fastcgi_param SCRIPT_NAME index.php;
}
}
FPM 핑/상태 페이지를 활성화했습니다. Nginx 포트 열기를 실행하는 데 사용할 수 있나요?
업데이트 1:
감독자 우선순위를 조정하고 초를 시작하려고 했습니다.
...
[program:php-fpm]
...
priority=100
startsecs=3
[program:nginx]
...
priority=200
그러나 성공하지 못했습니다.
[18-Dec-2020 00:31:04] NOTICE: ready to handle connections
[18-Dec-2020 00:31:04] NOTICE: fpm is running, pid 3
2020-12-18 00:30:30,689 INFO success: php-fpm entered RUNNING state, process has stayed up for > than 3 seconds (startsecs)
2020-12-18 00:30:28,388 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
Error POST 502 549 B 3.286 s Google-Cloud-Scheduler https://***.run.app/
169.254.8.129 - - [18/Dec/2020:00:30:27 +0000] "POST / HTTP/1.1" 502 150 "-" "Google-Cloud-Scheduler"
169.254.8.129 - - [18/Dec/2020:00:30:27 +0000] "POST / HTTP/1.1" 502 150 "-" "Google-Cloud-Scheduler" "35.187.131.214"
2020/12/18 00:30:27 [error] 6#6: *3 connect() failed (111: Connection refused) while connecting to upstream, client: 169.254.8.129, server: _, request: "POST / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "***.run.app"
2020-12-18 00:30:26,937 INFO spawned: 'nginx' with pid 4
2020-12-18 00:30:26,829 INFO spawned: 'php-fpm' with pid 3
2020-12-18 00:30:25,730 INFO supervisord started with pid 1
2020-12-18 00:30:25,704 CRIT Supervisor is running as root. Privileges were not dropped because no user
두 앱 모두 Supervisord에 의해 동시에 시작되었으며 nginx가 먼저 초기화됩니다. RUNNING
Supervisord가 앱에 적용하는 상태는 Cloud Run에 아무런 의미가 없습니다 .
답변1
지금은 nginx를 시작하기 전에 PHP-FPM이 실행되는지 확인하는 다음 진입점 스크립트를 사용했습니다.
#!/usr/bin/env sh
set -e
# Start PHP-FPM as a daemon in the background
php-fpm -D
# Wait until PHP-FPM is up and accepts connections. Fail if not started in 10 secs.
for run in $(seq 20)
do
if [ "$run" -gt "1" ]; then
echo "Retrying..."
fi
RESPONSE=$(
SCRIPT_NAME=/fpm-ping \
SCRIPT_FILENAME=/fpm-ping \
REQUEST_METHOD=GET \
cgi-fcgi -bind -connect 127.0.0.1:9000 || true)
case $RESPONSE in
*"pong"*)
echo "FPM is running and ready. Starting nginx."
# Run nginx without exiting to keep the container running
nginx -g 'daemon off;'
exit 0
;;
esac
sleep .5
done
echo "FPM has failed to start on-time, exiting"
exit 1
명령 apk add fcgi
이 필요합니다(Alpine Linux의 경우).
php-fpm -D
또한 FPM이 준비된 후에는 명령이 항상 종료되므로 루프가 필요하지 않고 명령을 하나씩 실행하면 된다고 가정합니다 . 그러나 나는 그것을 테스트하지 않았습니다.
답변2
감독자는 실제로 startdelay
옵션을 사용할 수 있지만 현재는 옵션이 없습니다. nginx 시작을 지연하려면 대신 Supervisor(관련 스레드):
쉘을 실행하여 잠자기 상태로 만든 다음 nginx를 직접 시작하십시오.
[program:nginx] command=bash -c "sleep 5 && exec nginx -g 'daemon off;'" ...
nginx를 시작하기 전에 절전 모드인 스크립트를 실행합니다.
[program:nginx] command=delayed-nginx.sh ...
delayed-nginx.sh
:#!/bin/bash sleep 5 exec nginx -g 'daemon off;'
원래 답변
저는 Supervisor를 특별히 사용하지는 않았지만이 답변당신에게 도움이 될 수도 있습니다. 이로 인해 Supervisor는 php-fpm
실행 중인 한 번만 nginx를 시작하게 됩니다 .
[program:php-fpm]
command=php-fpm -F
...
priority=100
[program:nginx]
command=nginx -g 'daemon off;'
...
priority=200
Supervisor가 오랜 시간(예: 5초) 동안 실행된 후에 startsecs
만 시작되는 것으로 간주하도록 더 높은 값(기본값 1초보다)으로 설정해야 할 수도 있습니다 .php-fpm
[program:php-fpm]
command=php-fpm -F
...
priority=100
startsecs=5