PHP-FPM + OPcache + Nginx + Capistrano stable deploy
Capistrano is great for deploying web applications. But the “current” symlink construction causes issues with PHP-FPM and OPcache enabled. PHP-FPM will display old pages after deployment or PHP-FPM just hangs. The hanging / freeze will result in your browser loading for minutes but you will just see a white screen.
To fix this, use $realpath_root instead of $document_root and set the SCRIPT_FILENAME in Nginx to pass to PHP-FPM.
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $realpath_root;
This will pass the actual path “releases/20150208145800″ to PHP-FPM instead of “current” that is switched to the new release directory. OPcache can’t detect this switch so it has to work with a real path. Read more about that at: https://github.com/zendtech/ZendOptimizerPlus/issues/126.
This worked a lot better, I could see in my browser that the new PHP files were used. However I still had about 60% of the time a white screen after deployment and a continuously loading browser.
I had to add the following to my Capistrano deployment script to fix this:
sudo service php5-fpm reload
I don’t like to use sudo for my “deployer” user, but with visudo you can give only specific sudo rights. So I find that acceptable and besides that, I couldn’t find any other working solution.
This is what I added to enable the use of the sudo command for reloading PHP-FPM without a password prompt:
deployer ALL=(root) NOPASSWD: /usr/bin/service php5-fpm reload
I’m using a similar setup (Ubuntu + PHP-FPM + nginx + Capistrano) but deploying for me does not require a restart of php-fpm. What versions are you using?
I use Ubuntu 13.10, PHP 5.5.3 (with Zend OpCache enabled), nginx 1.4.1 and Capistrano v2.15.5.
My server block looks like this:
listen 80;
root /var/www/testing.productr/current/web;
index index.php index.html index.htm;
server_name testing.productr.lillebi2;
location / {
# try to serve file directly, fallback to app.php
try_files $uri /app_testing.php$is_args$args;
}
location ~ ^/(app_testing)\.php(/|$) {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_param HTTPS off;
}
}
php modules:
..
Zend OPcache
...
[Zend Modules]
...
Zend OPcache
How does your setup differ from mine?