Назад | Перейти на главную страницу

Nginx кеширует символические ссылки

У меня есть система развертывания на моем веб-сервере, каждый раз, когда приложение развертывается, оно создает новый каталог с отметкой времени и символические ссылки "текущие" на новый каталог. Все это отлично работало на apache, но на новом сервере nginx, который я установил, похоже, что сценарий из «старого» развертывания запускается вместо нового, связанного с символической ссылкой.

Я прочитал несколько руководств и сообщений о том, как решить эту проблему, но информации мало, и, похоже, ничего не работает. Вот мой файл vhost:

server {
    listen 80;

    server_name ~^(www\.)?(?<sname>.+?).testing.domain.com$;
    root /var/www/$sname/current/public;
    index index.html index.htm index.php;

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

    location ~* \.(jpg|jpeg|gif|png|bmp|ico|pdf|flv|swf|exe|html|htm|txt|css|js) {
        add_header        Cache-Control public;
        add_header        Cache-Control must-revalidate;
        expires           7d;
    }

    location ~ \.php$ {
        #fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
        include fastcgi_params;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_index index.php;
    }

    location ~ /\.ht {
        deny all;
    }
}

а вот мой fastcgi_params:

fastcgi_param   SCRIPT_FILENAME         $document_root$fastcgi_script_name;
fastcgi_param   QUERY_STRING        $query_string;
fastcgi_param   REQUEST_METHOD      $request_method;
fastcgi_param   CONTENT_TYPE        $content_type;
fastcgi_param   CONTENT_LENGTH      $content_length;

fastcgi_param   SCRIPT_NAME     $fastcgi_script_name;
fastcgi_param   REQUEST_URI     $request_uri;
fastcgi_param   DOCUMENT_URI        $document_uri;
fastcgi_param   DOCUMENT_ROOT           $realpath_root;
fastcgi_param   SERVER_PROTOCOL     $server_protocol;

fastcgi_param   GATEWAY_INTERFACE   CGI/1.1;
fastcgi_param   SERVER_SOFTWARE     nginx/$nginx_version;

fastcgi_param   REMOTE_ADDR     $remote_addr;
fastcgi_param   REMOTE_PORT     $remote_port;
fastcgi_param   SERVER_ADDR     $server_addr;
fastcgi_param   SERVER_PORT     $server_port;
fastcgi_param   SERVER_NAME     $server_name;

fastcgi_param   HTTPS           $https if_not_empty;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param   REDIRECT_STATUS     200;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;

Я был бы очень признателен, если бы кто-нибудь мог мне помочь с этим, поскольку на данный момент каждое развертывание включает удаление предыдущего развертывания. Система - Ubuntu 14.04.5 LTS; PHP 7.1; Nginx nginx / 1.4.6 (Ubuntu)

Встроенные переменные, $realpath_root: абсолютный путь, соответствующий корень или псевдоним значение директивы для текущего запроса со всеми символическими ссылками, преобразованными в реальные пути

Решение использования $realpath_root вместо того $document_root скопировано на все сайты вопросов и ответов и форумы; на самом деле трудно не найти его, но я только хорошо его видел объяснил однажды Расмус Лердорф. Стоит поделиться, как он описывает Зачем это работает и когда его следует использовать.

Итак, когда вы развертываете что-то вроде Capistrano, который выполняет замену символических ссылок в корне документа, вы хотите, чтобы все новые запросы получали новые файлы, но вы не хотите отказываться от запросов, которые в настоящее время выполняются во время развертывания. Что вам действительно нужно для создания надежной среды развертывания, так это чтобы ваш веб-сервер отвечал за это. Веб-сервер - это часть стека, которая понимает, когда начинается новый запрос. Кэш опкодов находится слишком глубоко в стеке, чтобы знать об этом или заботиться об этом.

С nginx это довольно просто. Просто добавьте это в свою конфигурацию:

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;

Это говорит nginx о том, что realpath разрешает символическую ссылку docroot, что означает, что, насколько известно вашему PHP-приложению, целью символической ссылки является настоящий document_root. Теперь, после запуска запроса, nginx разрешит символическую ссылку в том виде, в котором она стоит в этой точке, и на протяжении всего запроса он будет использовать тот же каталог docroot, даже если переключение символической ссылки происходит в середине запроса. Это полностью устраняет описанные здесь симптомы и является правильным подходом. Это не то, что можно решить на уровне opcache.

Канишк Дудея были проблемы с этим и добавил полезное примечание: убедитесь, что эти изменения действительно будут в окончательной конфигурации, т.е. после include fastcgi_params; который в противном случае отменяет их.

Из https://unix.stackexchange.com/questions/157022/make-nginx-follow-symlinks, похоже, вы сможете обойти проблему, изменив

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

к

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;

(т.е. изменение пути с $document_root к $realpath_root).

В настоящее время у меня нет доступа к серверу nginx, чтобы подтвердить это (мой домашний сервер в настоящее время подвергается перестройке), но, похоже, с решением сотрудничает https://medium.com/@kanishkdudeja/truly-atomic-deployments-with-nginx-and-php-fpm-aed8a8ac1cd9.