Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Deploy your application in a box - DPC2016

Deploy your application in a box - DPC2016

Willem-Jan Zijderveld

June 24, 2016
Tweet

More Decks by Willem-Jan Zijderveld

Other Decks in Programming

Transcript

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

    Update code dependencies (composer,npm,bower) Clear cache Reload webserver
  2. > 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
  3. Example: after > ssh [email protected] > ./deploy.sh * Pulling changes

    * Updating dependencies * Migrating database * Clearing cache * DEPLOYED NEW VERSION
  4. Legacy code? Test the critical parts - Unit tests for

    important (domain) logic - Functional tests - Monitor production
  5. 6 month projects Deliver something every day Don't wait with

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

    huge merge conflicts • Speeds up overall development
  7. 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); }
  8. 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); }
  9. Example: Conditional toggle <?php $toggle = new Toggle( 'recommendations', ['user_id'

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

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

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

    => GreaterThan(42)] ); $toggle->active(['user_id' => 21]); // true $toggle->active(['user_id' => 1337]); // false
  13. More often - Smaller iterations - Don't wait for the

    whole feature to complete - Make use of feature toggles
  14. 0 downtime - Don't touch the current version - Abort

    when any of the steps fail - Make your migrations backwards compatible
  15. 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
  16. <?php // Uploader.php function uploadAvatar($filename) { $stream = fopen($filename, 'r+');

    $this->filesystem ->writeStream('avatars/' . $filename, $stream); if (is_resource($stream)) { fclose($stream); } }
  17. # 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
  18. # 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%
  19. # 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%
  20. # 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%
  21. <?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); } }
  22. <?php // web/index.php $dotenv = new Dotenv\Dotenv(__DIR__ . '/../'); $dotenv->load();

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

    dependencies on environment - Give control to the environment
  24. 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