Slide 1

Slide 1 text

THE TWELVE-FACTOR APP Best Practices for Modern PHP Applications

Slide 2

Slide 2 text

David Zuelke

Slide 3

Slide 3 text

David Zülke

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Slide 6

Slide 6 text

@dzuelke

Slide 7

Slide 7 text

“The Twelve-Factor App” ! ! !

Slide 8

Slide 8 text

“The Twelve-Factor App” is a manifesto, a methodology, a condensed collection of experiences.

Slide 9

Slide 9 text

Its goals are scalability, maintainability, portability.

Slide 10

Slide 10 text

I. CODEBASE One codebase, many deploys.

Slide 11

Slide 11 text

I. CODEBASE One codebase, many deploys. Git, Mercurial, SVN, even CVS are okay. A samba share is never okay. Neither are floppy disks.

Slide 12

Slide 12 text

II. DEPENDENCIES Applications have explicitly declared dependencies.

Slide 13

Slide 13 text

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"          }   }

Slide 14

Slide 14 text

III. CONFIGURATION Store config in the environment.

Slide 15

Slide 15 text

III. CONFIGURATION Store config in the environment. Assumption: same code but different configuration per deployment target

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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.

Slide 18

Slide 18 text

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.

Slide 19

Slide 19 text

X. DEV/PROD PARITY Keep dev, stage and prod envs as similar as possible.

Slide 20

Slide 20 text

X. DEV/PROD PARITY Keep dev, stage and prod envs as similar as possible. SQLite ≠ MySQL Apache ≠ Nginx File based sessions ≠ Redis based sessions

Slide 21

Slide 21 text

X. DEV/PROD PARITY Keep dev, stage and prod envs as similar as possible. SQLite ≠ MySQL Apache ≠ Nginx File based sessions ≠ Redis based sessions

Slide 22

Slide 22 text

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!

Slide 23

Slide 23 text

XI. LOGGING Treat your logs as a stream of events.

Slide 24

Slide 24 text

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.

Slide 25

Slide 25 text

XII. ADMIN PROCESSES Management tasks like DB migrations are one-off processes.

Slide 26

Slide 26 text

XII. ADMIN PROCESSES Management tasks like DB migrations are one-off processes. The same release, the same config, the same code!

Slide 27

Slide 27 text

PHP ON HEROKU Putting it all together!

Slide 28

Slide 28 text

$  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

Slide 29

Slide 29 text

DEMO TIME!

Slide 30

Slide 30 text

http://start.heroku.com/php & http://devcenter.heroku.com/categories/php

Slide 31

Slide 31 text

DEV/PROD PARITY

Slide 32

Slide 32 text

heroku-­‐python-­‐app  $  cat  Procfile   web:  gunicorn  hello:app

Slide 33

Slide 33 text

heroku-­‐ruby-­‐app  $  cat  Procfile   web:  bundle  exec  unicorn  -­‐p  $PORT  -­‐c  ./config/unicorn.rb

Slide 34

Slide 34 text

heroku-­‐java-­‐app  $  cat  Procfile   web:  java  -­‐jar  target/dependency/jetty-­‐runner.jar  -­‐-­‐port  $PORT   target/*.war

Slide 35

Slide 35 text

heroku-­‐php-­‐app  $  cat  Procfile   web:  php  -­‐S  0.0.0.0:$PORT

Slide 36

Slide 36 text

PHP needs a dedicated web server

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

(only needed if you want to run things locally)

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

ONE MORE THING...

Slide 41

Slide 41 text

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'

Slide 42

Slide 42 text

YET ANOTHER THING...

Slide 43

Slide 43 text

GET A FREE HEROKU T-SHIRT!

Slide 44

Slide 44 text

The End

Slide 45

Slide 45 text

THE TWELVE- FACTOR APP rate my talk on joind.in! Thanks for listening! Contact: @dzuelke & [email protected].