Share
Embed
The Twelve-Factor App (and PHP on Heroku)
Best practices for modern PHP apps. Presented at International PHP Conference Spring Edition 2014 in Berlin, Germany.
David Zuelke
June 03, 2014
Transcript
40 slides
-
“The Twelve-Factor App” is a manifesto, a methodology, a condensed
collection of experiences. -
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. $ 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. 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 If apt-‐get or brew don't get the job done: Vagrant is always your friend! -
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. The same release, the same config, the same code! -
$ heroku create $ git push heroku master -‐-‐-‐-‐-‐> PHP
app detected -‐-‐-‐-‐-‐> Setting up runtime environment... -‐ PHP 5.5.12 -‐ Apache 2.4.9 -‐ Nginx 1.4.6 -‐-‐-‐-‐-‐> 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 -
heroku-‐ruby-‐app $ cat Procfile web: bundle exec unicorn -‐p $PORT
-‐c ./config/unicorn.rb -
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 (v15) Loading from cache Writing lock file Generating autoload files -
heroku-‐php-‐app $ foreman start 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 -
heroku-‐php-‐app $ git rm Procfile heroku-‐php-‐app $ hhvm `which composer`
require hhvm 3.0.1 ./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.0.1 in composer.json. -‐-‐-‐-‐-‐> Setting up runtime environment... -‐ HHVM 3.0.1 -‐ Apache 2.4.9 -‐ Nginx 1.4.6 -‐-‐-‐-‐-‐> Building runtime environment... NOTICE: No Procfile, defaulting to 'web: vendor/bin/ heroku-‐hhvm-‐apache2'