PHP ON HEROKU 
David Zuelke 
Heroku 
dz@heroku.com 
@dzuelke 
Dreamforce 2014
David Zuelke
David Zülke
“The Twelve-Factor App” 
is 
a manifesto, 
a methodology, 
a condensed collection of experiences.
Its goals are 
scalability, 
maintainability, 
portability.
I. CODEBASE 
One codebase, many deploys.
I. CODEBASE 
One codebase, many deploys. 
Git, Mercurial, SVN, even CVS are okay. 
A samba share is never okay. 
Neither are floppy disks.
II. DEPENDENCIES 
Applications have explicitly declared dependencies.
II. DEPENDENCIES 
Applications have explicitly declared dependencies. 
$ cat composer.json 
{ 
"require": { 
"php": ">=5.3.3", 
"ext-mcrypt": "*", 
"symfony/symfony": "~2.4.6", 
"doctrine/orm": "~2.2,>=2.2.3", 
"doctrine/doctrine-bundle": "~1.2", 
"twig/extensions": "~1.0", 
"symfony/monolog-bundle": "~2.4" 
} 
}
III. CONFIGURATION 
Store config in the environment.
III. CONFIGURATION 
Store config in the environment. 
Assumption: 
same code but different configuration per deployment target
III. CONFIGURATION 
Store config in the environment. 
$transport = Swift_SmtpTransport::newInstance( 
getenv('EMAIL_HOST'), getenv('EMAIL_PORT')?:25 
) 
->setUsername(getenv('EMAIL_USERNAME')) 
->setPassword(getenv('EMAIL_PASSWORD')) 
; 
Assumption: 
same code but different configuration per deployment target
V. BUILD, RELEASE, RUN 
A build step vendors dependencies, prepares assets, etc. 
A release step creates a package from build and config. 
A runtime step executes, without special knowledge.
V. BUILD, RELEASE, RUN 
A build step vendors dependencies, prepares assets, etc. 
A release step creates a package from build and config. 
A runtime step executes, without special knowledge.
X. DEV/PROD PARITY 
Keep dev, stage and prod envs as similar as possible.
X. DEV/PROD PARITY 
Keep dev, stage and prod envs as similar as possible. 
SQLite ≠ MySQL 
Apache ≠ Nginx 
File based sessions ≠ Redis based sessions
X. DEV/PROD PARITY 
Keep dev, stage and prod envs as similar as possible. 
SQLite ≠ MySQL 
Apache ≠ Nginx 
File based sessions ≠ Redis based sessions
X. DEV/PROD PARITY 
Keep dev, stage and prod envs as similar as possible. 
SQLite ≠ MySQL 
Apache ≠ Nginx 
File based sessions ≠ Redis based sessions 
If apt-get or brew don't get the job done on your box: 
Vagrant is always your friend!
XI. LOGGING 
Treat your logs as a stream of events.
XI. LOGGING 
Treat your logs as a stream of events. 
Stop rotating logs and so forth in your app. 
Let the runtime worry about it. 
Log to STDOUT/STDERR. 
Centrally archive it.
XII. ADMIN PROCESSES 
Management tasks like DB migrations are one-off processes.
XII. ADMIN PROCESSES 
Management tasks like DB migrations are one-off processes. 
The same release, 
the same config, 
the same code!
PHP ON HEROKU 
• Putting it all together!
$ heroku create 
$ git push heroku master 
-----> PHP app detected 
-----> Setting up runtime environment... 
- PHP 5.5.16 
- Apache 2.4.10 
- Nginx 1.6.0 
-----> Installing PHP extensions: 
- opcache (automatic; bundled) 
- memcached (composer.json; downloaded) 
- intl (composer.json; bundled) 
- newrelic (add-on detected; downloaded) 
-----> Installing dependencies... 
Composer version 05d991 2014-04-29 12:36:19 
Loading composer repositories with package information 
Installing dependencies from lock file 
- Installing psr/log (1.0.0) 
Loading from cache 
- Installing monolog/monolog (1.9.1) 
Loading from cache 
Generating optimized autoload files
DEMO TIME!
DEV/PROD PARITY
heroku-python-app $ cat Procfile 
web: gunicorn hello:app
heroku-ruby-app $ cat Procfile 
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
heroku-java-app $ cat Procfile 
web: java -jar target/dependency/jetty-runner.jar --port $PORT 
target/*.war
heroku-php-app $ cat Procfile 
web: php -S 0.0.0.0:$PORT
PHP needs a dedicated web server
heroku-php-app $ cat Procfile 
web: vendor/bin/heroku-php-nginx 
heroku-php-app $ composer require --dev heroku/heroku-buildpack-php 
./composer.json has been updated 
Loading composer repositories with package information 
Updating dependencies (including require-dev) 
- Installing heroku/heroku-buildpack-php (v43) 
Loading from cache 
Writing lock file 
Generating autoload files
(only needed if you want to run things locally)
17:47:26 web.1 | started with pid 70338 
17:47:26 web.1 | Booting on port 5000... 
17:47:26 web.1 | Using PHP-FPM configuration file 
'vendor/heroku/heroku-buildpack-php/conf/php/php-fpm.conf' 
17:47:26 web.1 | Using PHP configuration (php.ini) file 
'vendor/heroku/heroku-buildpack-php/conf/php/php.ini' 
17:47:26 web.1 | Using Nginx server-level configuration include 
'vendor/heroku/heroku-buildpack-php/conf/nginx/default_include.conf' 
17:47:27 web.1 | Using Nginx configuration file 'vendor/heroku/heroku-buildpack- 
php/conf/nginx/heroku.conf.php' 
17:47:27 web.1 | Interpreting vendor/heroku/heroku-buildpack-php/ 
conf/nginx/heroku.conf.php to heroku.conf 
17:47:27 web.1 | Starting log redirection... 
17:47:27 web.1 | Starting php-fpm... 
17:47:27 web.1 | Starting nginx... 
17:47:27 web.1 | [29-Apr-2014 17:47:27] NOTICE: [pool www] 'user' 
directive is ignored when FPM is not running as root 
17:47:27 web.1 | [29-Apr-2014 17:47:27] NOTICE: [pool www] 'user' 
directive is ignored when FPM is not running as root 
17:47:27 web.1 | [29-Apr-2014 17:47:27] NOTICE: fpm is running, pid 
70379 
17:47:27 web.1 | [29-Apr-2014 17:47:27] NOTICE: ready to handle 
connections
ONE MORE THING...
heroku-php-app $ git rm Procfile 
heroku-php-app $ hhvm `which composer` require hhvm ~3.2 
./composer.json has been updated 
Loading composer repositories with package information 
Updating dependencies (including require-dev) 
Nothing to install or update 
Generating autoload files 
heroku-php-app $ git add composer.* 
heroku-php-app $ git ci -m 'use HHVM' 
heroku-php-app $ git push heroku master 
-----> PHP app detected 
-----> Detected request for HHVM 3.2.0 in composer.json. 
-----> Setting up runtime environment... 
- HHVM 3.2.0 
- Apache 2.4.10 
- Nginx 1.6.0 
-----> Building runtime environment... 
NOTICE: No Procfile, defaulting to 'web: vendor/bin/heroku-hhvm-apache2'
The End
PHP ON HEROKU 
Further reading: 
http://12factor.net/ 
http://devcenter.heroku.com/categories/php 
I'm @dzuelke, thank you for listening :)
PHP on Heroku: Deploying and Scaling Apps in the Cloud

PHP on Heroku: Deploying and Scaling Apps in the Cloud

  • 1.
    PHP ON HEROKU David Zuelke Heroku [email protected] @dzuelke Dreamforce 2014
  • 2.
  • 3.
  • 5.
    “The Twelve-Factor App” is a manifesto, a methodology, a condensed collection of experiences.
  • 6.
    Its goals are scalability, maintainability, portability.
  • 7.
    I. CODEBASE Onecodebase, many deploys.
  • 8.
    I. CODEBASE Onecodebase, many deploys. Git, Mercurial, SVN, even CVS are okay. A samba share is never okay. Neither are floppy disks.
  • 9.
    II. DEPENDENCIES Applicationshave explicitly declared dependencies.
  • 10.
    II. DEPENDENCIES Applicationshave explicitly declared dependencies. $ cat composer.json { "require": { "php": ">=5.3.3", "ext-mcrypt": "*", "symfony/symfony": "~2.4.6", "doctrine/orm": "~2.2,>=2.2.3", "doctrine/doctrine-bundle": "~1.2", "twig/extensions": "~1.0", "symfony/monolog-bundle": "~2.4" } }
  • 11.
    III. CONFIGURATION Storeconfig in the environment.
  • 12.
    III. CONFIGURATION Storeconfig in the environment. Assumption: same code but different configuration per deployment target
  • 13.
    III. CONFIGURATION Storeconfig in the environment. $transport = Swift_SmtpTransport::newInstance( getenv('EMAIL_HOST'), getenv('EMAIL_PORT')?:25 ) ->setUsername(getenv('EMAIL_USERNAME')) ->setPassword(getenv('EMAIL_PASSWORD')) ; Assumption: same code but different configuration per deployment target
  • 14.
    V. BUILD, RELEASE,RUN A build step vendors dependencies, prepares assets, etc. A release step creates a package from build and config. A runtime step executes, without special knowledge.
  • 15.
    V. BUILD, RELEASE,RUN A build step vendors dependencies, prepares assets, etc. A release step creates a package from build and config. A runtime step executes, without special knowledge.
  • 16.
    X. DEV/PROD PARITY Keep dev, stage and prod envs as similar as possible.
  • 17.
    X. DEV/PROD PARITY Keep dev, stage and prod envs as similar as possible. SQLite ≠ MySQL Apache ≠ Nginx File based sessions ≠ Redis based sessions
  • 18.
    X. DEV/PROD PARITY Keep dev, stage and prod envs as similar as possible. SQLite ≠ MySQL Apache ≠ Nginx File based sessions ≠ Redis based sessions
  • 19.
    X. DEV/PROD PARITY Keep dev, stage and prod envs as similar as possible. SQLite ≠ MySQL Apache ≠ Nginx File based sessions ≠ Redis based sessions If apt-get or brew don't get the job done on your box: Vagrant is always your friend!
  • 20.
    XI. LOGGING Treatyour logs as a stream of events.
  • 21.
    XI. LOGGING Treatyour logs as a stream of events. Stop rotating logs and so forth in your app. Let the runtime worry about it. Log to STDOUT/STDERR. Centrally archive it.
  • 22.
    XII. ADMIN PROCESSES Management tasks like DB migrations are one-off processes.
  • 23.
    XII. ADMIN PROCESSES Management tasks like DB migrations are one-off processes. The same release, the same config, the same code!
  • 24.
    PHP ON HEROKU • Putting it all together!
  • 25.
    $ heroku create $ git push heroku master -----> PHP app detected -----> Setting up runtime environment... - PHP 5.5.16 - Apache 2.4.10 - Nginx 1.6.0 -----> Installing PHP extensions: - opcache (automatic; bundled) - memcached (composer.json; downloaded) - intl (composer.json; bundled) - newrelic (add-on detected; downloaded) -----> Installing dependencies... Composer version 05d991 2014-04-29 12:36:19 Loading composer repositories with package information Installing dependencies from lock file - Installing psr/log (1.0.0) Loading from cache - Installing monolog/monolog (1.9.1) Loading from cache Generating optimized autoload files
  • 26.
  • 27.
  • 28.
    heroku-python-app $ catProcfile web: gunicorn hello:app
  • 29.
    heroku-ruby-app $ catProcfile web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
  • 30.
    heroku-java-app $ catProcfile web: java -jar target/dependency/jetty-runner.jar --port $PORT target/*.war
  • 31.
    heroku-php-app $ catProcfile web: php -S 0.0.0.0:$PORT
  • 32.
    PHP needs adedicated web server
  • 33.
    heroku-php-app $ catProcfile web: vendor/bin/heroku-php-nginx heroku-php-app $ composer require --dev heroku/heroku-buildpack-php ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) - Installing heroku/heroku-buildpack-php (v43) Loading from cache Writing lock file Generating autoload files
  • 34.
    (only needed ifyou want to run things locally)
  • 35.
    17:47:26 web.1 |started with pid 70338 17:47:26 web.1 | Booting on port 5000... 17:47:26 web.1 | Using PHP-FPM configuration file 'vendor/heroku/heroku-buildpack-php/conf/php/php-fpm.conf' 17:47:26 web.1 | Using PHP configuration (php.ini) file 'vendor/heroku/heroku-buildpack-php/conf/php/php.ini' 17:47:26 web.1 | Using Nginx server-level configuration include 'vendor/heroku/heroku-buildpack-php/conf/nginx/default_include.conf' 17:47:27 web.1 | Using Nginx configuration file 'vendor/heroku/heroku-buildpack- php/conf/nginx/heroku.conf.php' 17:47:27 web.1 | Interpreting vendor/heroku/heroku-buildpack-php/ conf/nginx/heroku.conf.php to heroku.conf 17:47:27 web.1 | Starting log redirection... 17:47:27 web.1 | Starting php-fpm... 17:47:27 web.1 | Starting nginx... 17:47:27 web.1 | [29-Apr-2014 17:47:27] NOTICE: [pool www] 'user' directive is ignored when FPM is not running as root 17:47:27 web.1 | [29-Apr-2014 17:47:27] NOTICE: [pool www] 'user' directive is ignored when FPM is not running as root 17:47:27 web.1 | [29-Apr-2014 17:47:27] NOTICE: fpm is running, pid 70379 17:47:27 web.1 | [29-Apr-2014 17:47:27] NOTICE: ready to handle connections
  • 36.
  • 37.
    heroku-php-app $ gitrm Procfile heroku-php-app $ hhvm `which composer` require hhvm ~3.2 ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Nothing to install or update Generating autoload files heroku-php-app $ git add composer.* heroku-php-app $ git ci -m 'use HHVM' heroku-php-app $ git push heroku master -----> PHP app detected -----> Detected request for HHVM 3.2.0 in composer.json. -----> Setting up runtime environment... - HHVM 3.2.0 - Apache 2.4.10 - Nginx 1.6.0 -----> Building runtime environment... NOTICE: No Procfile, defaulting to 'web: vendor/bin/heroku-hhvm-apache2'
  • 38.
  • 39.
    PHP ON HEROKU Further reading: http://12factor.net/ http://devcenter.heroku.com/categories/php I'm @dzuelke, thank you for listening :)