Liens symboliques de mise en cache Nginx

12

J'ai un système de déploiement sur mon serveur Web, chaque fois qu'une application est déployée, elle crée un nouveau répertoire horodaté et des liens symboliques "actuels" vers le nouveau répertoire. Tout cela fonctionnait bien sur Apache, mais sur le nouveau serveur nginx que j'ai configuré, il semble qu'un script de «l'ancien» déploiement est en cours d'exécution au lieu du nouveau lien symbolique.

J'ai lu des tutoriels et des articles sur la façon de résoudre ce problème, mais il n'y a pas beaucoup d'informations et rien ne semble fonctionner. Voici mon fichier 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;
    }
}

et voici mes 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;

J'apprécierais vraiment si quelqu'un pouvait m'aider avec cela car pour le moment, chaque déploiement implique la suppression du déploiement précédent. Le système est Ubuntu 14.04.5 LTS; PHP 7.1; Nginx nginx / 1.4.6 (Ubuntu)

Auris
la source

Réponses:

22

Variables intégrées , $realpath_root: un chemin absolu correspondant à la racine ou alias la valeur de directive pour la demande actuelle, avec tous les liens symboliques résolus à des chemins réels

La solution d'utiliser $realpath_rootau lieu de $document_rootest copiée-collée tout autour des sites Q / A et des forums; il est en fait difficile de ne pas le trouver, mais je ne l'ai vu bien expliqué qu'une seule fois par Rasmus Lerdorf . Cela vaut la peine d'être partagé car il décrit pourquoi cela fonctionne et quand il doit être utilisé.

Ainsi, lorsque vous déployez via quelque chose comme Capistrano qui effectue un échange de lien symbolique à la racine du document, vous voulez que toutes les nouvelles demandes obtiennent les nouveaux fichiers, mais vous ne voulez pas visser les demandes en cours d'exécution pendant le déploiement. Ce dont vous avez vraiment besoin pour créer un environnement de déploiement robuste, c'est d'avoir votre serveur Web en charge. Le serveur Web est la partie de la pile qui comprend quand une nouvelle demande démarre. Le cache d'opcode est trop profond dans la pile pour le savoir ou s'en soucier.

Avec nginx, c'est assez simple. Ajoutez simplement ceci à votre configuration:

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

Cela indique à nginx de résoudre le lien symbolique vers le chemin réel, ce qui signifie que, pour autant que votre application PHP le sache, la cible du lien symbolique est le vrai document_root. Maintenant, une fois qu'une requête démarre, nginx résoudra le lien symbolique tel qu'il est à ce point et pendant la durée de la demande, il utilisera le même répertoire docroot, même si le commutateur de lien symbolique se produit à la mi-requête. Cela élimine complètement les symptômes décrits ici et c'est la bonne approche. Ce n'est pas quelque chose qui peut être résolu au niveau de l'opcache.

Kanishk Dudeja a eu des problèmes avec cela et a ajouté une remarque utile: assurez-vous que ces changements seront réellement dans la configuration finale, c'est-à-dire après include fastcgi_params;quoi ils les remplaceront.

Esa Jokinen
la source
Salut, c'est une excellente réponse, mais si vous remarquez dans ma configuration, j'ai fastcgi_param DOCUMENT_ROOT $ realpath_root; fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name; inclus après fastcgi_params, et cela n'aide pas vraiment. Lorsque je redémarre php-fpm, les liens symboliques sont résolus. Cela indiquerait-il que j'ai un problème de mise en cache php à la place?
Auris
Réviser. Ce SCRIPT_FILENAMEn'est $document_rootpas le cas $realpath_root.
Esa Jokinen
Hmm ... mais il DOCUMENT_ROOTest réglé pour $realpath_rootque je le comprenne, il devrait enchaîner la valeur ou je me trompe complètement et DOCUMENT_ROOTn'est pas lié à$document_root
Auris
1
Salut, merci beaucoup pour votre réponse et votre explication, mon erreur était l'hypothèse qui DOCUMENT_ROOTaffecte$document root
Auris
2
J'utilise Apache + php-fpm sur les serveurs avec ce problème et la suppression de l'opcached sur le déploiement a fonctionné pour moi, nous avons un script bash pour le déploiement, pas Capistrano cependant. Je pense que c'est une solution plus simple et c'est une bonne pratique pour effacer votre opcache lors du déploiement de toute façon. Esa remercie pour le lien vers le commentaire Rasmus qui est d'or!
Carlos Mafla
3

Depuis /unix/157022/make-nginx-follow-symlinks , il semble que vous puissiez peut-être contourner le problème en modifiant

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

à

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;

(c.-à-d. changer le chemin de $document_rootà $realpath_root).

Je n'ai pas accès à un serveur nginx pour le moment (mon serveur domestique est actuellement en cours de reconstruction), mais la solution semble être collaborée par https://medium.com/@kanishkdudeja/truly-atomic-deployments -avec-nginx-et-php-fpm-aed8a8ac1cd9 .

Pak
la source