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. 12.
  2. 22.
  3. 28.

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

    Update code dependencies (composer,npm,bower) Clear cache Reload webserver
  4. 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
  5. 30.

    Example: after > ssh deploy@your-server.com > ./deploy.sh * Pulling changes

    * Updating dependencies * Migrating database * Clearing cache * DEPLOYED NEW VERSION
  6. 32.
  7. 35.

    Legacy code? Test the critical parts - Unit tests for

    important (domain) logic - Functional tests - Monitor production
  8. 39.

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

    deploying until your feature is ready and approved.
  9. 40.

    Short lived branches • Allows for rapid deployment • Prevents

    huge merge conflicts • Speeds up overall development
  10. 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); }
  11. 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); }
  12. 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
  13. 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
  14. 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
  15. 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
  16. 51.

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

    whole feature to complete - Make use of feature toggles
  17. 64.

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

    when any of the steps fail - Make your migrations backwards compatible
  18. 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
  19. 77.

    <?php // Uploader.php function uploadAvatar($filename) { $stream = fopen($filename, 'r+');

    $this->filesystem ->writeStream('avatars/' . $filename, $stream); if (is_resource($stream)) { fclose($stream); } }
  20. 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
  21. 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%
  22. 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%
  23. 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%
  24. 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); } }
  25. 89.

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

    Load .env # .env MYAPP_S3_PRIVATE_FILES_BUCKET=yourbucket
  26. 90.

    Building the box - Should be reusable - Eliminate hard

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