Deploy your application in a box - DPC2016

Deploy your application in a box - DPC2016

C347affc11bc313dc3da2398936d305a?s=128

Willem-Jan Zijderveld

June 24, 2016
Tweet

Transcript

  1. Deploy your application in a box @willemjanz joind.in/talk/73636

  2. Willem-Jan Zijderveld @willemjanz github.com/wjzijderveld

  3. Don't wait till the last slide with questions

  4. Deployment With the usual disclaimer

  5. It works So why change it?

  6. Can you deploy whenever you want?

  7. Are you ever hesitant to deploy?

  8. "We can't deploy, Robin is sick today"

  9. Do users notice when you deploy?

  10. Things break If you like it or not

  11. Deployments fail • Network issues • Migrations • Broken configuration

  12. Downtime

  13. Missed revenue

  14. Angry customers

  15. Customers losing faith

  16. Scared to deploy

  17. Deployments get postponed

  18. Reserving dedicated time to deploy

  19. Deploying outside office hours...

  20. So what would be a more optimal method?

  21. Less humans

  22. No sweat

  23. More often

  24. 0 downtime

  25. Repeatable

  26. Let's get started

  27. Less humans Automate your deploy process to a single step

  28. Possible deployment Migrate database Update code on server (FTP, SSH)

    Update code dependencies (composer,npm,bower) Clear cache Reload webserver
  29. > ssh your-server.com > sudo su - > cd /var/www/

    > git pull > php composer.phar install > npm install > rm -rf app/cache/* > # Some permission commands > service php-fpm reload Example: before
  30. Example: after > ssh deploy@your-server.com > ./deploy.sh * Pulling changes

    * Updating dependencies * Migrating database * Clearing cache * DEPLOYED NEW VERSION
  31. No sweat Lose the fear of deploying

  32. Testing

  33. Seriously, test your code

  34. New code should have tests

  35. Legacy code? Test the critical parts - Unit tests for

    important (domain) logic - Functional tests - Monitor production
  36. Continuous Integration

  37. More often

  38. Smaller changes

  39. 6 month projects Deliver something every day Don't wait with

    deploying until your feature is ready and approved.
  40. Short lived branches • Allows for rapid deployment • Prevents

    huge merge conflicts • Speeds up overall development
  41. Feature toggles

  42. Example: recommendations <?php // BasketController.php function actionBasket(User $user) { $basket

    = $this->getBasketOfUser($user); $response = ['basket' => $basket->toArray()]; if ($this->featureIsActive('recommendations')) { $response['recommendations'] = $this->getRecommendations($basket); } return new JsonResponse($response); }
  43. Example: recommendations <?php // BasketController.php function actionBasket(User $user) { $basket

    = $this->getBasketOfUser($user); $response = ['basket' => $basket->toArray()]; if ($this->featureIsActive('recommendations')) { $response['recommendations'] = $this->getRecommendations($basket); } return new JsonResponse($response); }
  44. Give some users access

  45. Conditional toggle Check the context against the conditions of the

    toggle
  46. Example: Conditional toggle <?php $toggle = new Toggle( 'recommendations', ['user_id'

    => GreaterThan(42)] ); $toggle->active(['user_id' => 21]); // true $toggle->active(['user_id' => 1337]); // false
  47. Example: Conditional toggle <?php $toggle = new Toggle( 'recommendations', ['user_id'

    => GreaterThan(42)] ); $toggle->active(['user_id' => 21]); // true $toggle->active(['user_id' => 1337]); // false
  48. Example: Conditional toggle <?php $toggle = new Toggle( 'recommendations', ['user_id'

    => GreaterThan(42)] ); $toggle->active(['user_id' => 21]); // true $toggle->active(['user_id' => 1337]); // false
  49. Example: Conditional toggle <?php $toggle = new Toggle( 'recommendations', ['user_id'

    => GreaterThan(42)] ); $toggle->active(['user_id' => 21]); // true $toggle->active(['user_id' => 1337]); // false
  50. Feature management GUI API Redis http://labs.qandidate.com/blog/2014/08/19/open-sourcing-our-feature-toggle-api-and-ui/

  51. More often - Smaller iterations - Don't wait for the

    whole feature to complete - Make use of feature toggles
  52. 0 downtime

  53. Prepare your deployment

  54. Deployment Webserver Application - version 1

  55. Deployment Webserver Application - version 1 Application - version 2

  56. Deployment Webserver Application - version 1 Application - version 2

  57. Deployment Webserver Application - version 1

  58. Deployment Webserver Application - version 1 Install code

  59. Deployment Webserver Application - version 1 Install code Migrations

  60. Deployment Webserver Application - version 1 Install code Migrations Warmup

    cache
  61. Deployment Webserver Application - version 1 Install code Migrations Warmup

    cache Application - version 2
  62. Deployment Webserver Application - version 1 Install code Migrations Warmup

    cache Application - version 2
  63. Example /var /project /releases /20160608-1.0 /20160609-1.1 /current -> /var/project/releases/20160608-1.0

  64. 0 downtime - Don't touch the current version - Abort

    when any of the steps fail - Make your migrations backwards compatible
  65. Put it in a box

  66. Repeatable

  67. Environment independent

  68. The box In it's simplest form: just a zip

  69. Independent

  70. Reusable On all environments

  71. Some challenges

  72. Filesystem

  73. <!-- services.xml --> <services> <service id="uploader" class="AppBundle\Uploader"> <argument>/var/www/uploads/</argument> </service> </services>

  74. Flysystem Abstract the filesystem - Makes it easier to test

    - Makes your code independent of the filesystem, f.e.: - Production uses S3 - Development uses local files
  75. <!-- services.xml --> <services> <service id="uploader" class="AppBundle\Uploader"> <argument type="service" id="oneup_flysystem.private_filesystem"

    /> </service> </services>
  76. # config.yml oneup_flysystem: adapters: private_s3: awss3v2: client: aws_s3_client bucket: %s3_private_files_bucket%

    filesystem: private: adapter: private_s3
  77. <?php // Uploader.php function uploadAvatar($filename) { $stream = fopen($filename, 'r+');

    $this->filesystem ->writeStream('avatars/' . $filename, $stream); if (is_resource($stream)) { fclose($stream); } }
  78. File is now at S3: bucket/avatars/filename. ext

  79. Configuration

  80. # config_prod.yml imports: - { resource: config.yml } doctrine: dbal:

    default_connection: default connections: default: driver: pdo_mysql host: 192.168.1.10 dbname: acme_prod user: acme_prod password: SuperSecure
  81. What about staging and acceptance?

  82. Give control to the environment

  83. # config.yml imports: - { resource: parameters.yml } - {

    resource: parameters.php } doctrine: dbal: default_connection: default connections: default: driver: pdo_mysql host: %db.hostname% dbname: %db.name% user: %db.user% password: %db.password%
  84. # config.yml imports: - { resource: parameters.yml } - {

    resource: parameters.php } doctrine: dbal: default_connection: default connections: default: driver: pdo_mysql host: %db.hostname% dbname: %db.name% user: %db.user% password: %db.password%
  85. # config.yml imports: - { resource: parameters.yml } - {

    resource: parameters.php } doctrine: dbal: default_connection: default connections: default: driver: pdo_mysql host: %db.hostname% dbname: %db.name% user: %db.user% password: %db.password%
  86. <?php // parameters.php $parameterMapping = [ 's3_private_files_bucket' => 'MYAPP_S3_PRIVATE_FILES_BUCKET', ];

    foreach ($parameterMapping as $parameter => $env) { if (false !== ($value = getenv($env))) { $container->setParameter($parameter, $value); } }
  87. $_ENV['SYMFONY__*'] But those values get overwritten by parameters defined in

    config.yml / parameters.yml
  88. PHP dot env https://github.com/vlucas/phpdotenv

  89. <?php // web/index.php $dotenv = new Dotenv\Dotenv(__DIR__ . '/../'); $dotenv->load();

    Load .env # .env MYAPP_S3_PRIVATE_FILES_BUCKET=yourbucket
  90. Building the box - Should be reusable - Eliminate hard

    dependencies on environment - Give control to the environment
  91. Summary - Less manual steps, eliminate the humans - Lose

    the fear: test your stuff - Deploy more often, don't postpone - Deployment shouldn't cause downtime - A deployment should be repeatable
  92. Other questions? @willemjanz Please leave some feedback! joind.in/talk/73636