Dwight Watson's blog

Deploying Laravel with Envoy

This blog post was originally published a little while ago. Please consider that it may no longer be relevant or even accurate.

On a recent project we moved a site from a single server to a series of AWS EC2 instances provisioned with Laravel Forge. With this change we needed to re-think the way we did deployments as they now had to be applied to multiple servers, and we wanted to do it easily and fast. With that in mind we decided to take a look at Envoy, Laravel's task runner.

Here are some excepts from our envoy.blade.php file, which might be useful to someone else who is considering deployment through Envoy. I've added a little bit of information to each Envoy task to explain what it is and why we use it.

This is the primary deployment task - it deploys the latest code from the master branch to our two web instances and our worker (queues and crons). We run composer install as well to get any new dependencies but opt out of development dependencies (not necessary) and use the --prefer-dist flag to get distribution copies of the dependencies as they should download faster. We don't use parallel deployment in case something goes wrong during deployment so we still have other servers going.

@task('production:deploy', ['on' => ['web1', 'web2', 'worker1']])
cd default
php artisan down
git pull origin master --force
composer install --no-dev --prefer-dist
php artisan up
@endtask

Just utility tasks to turn the application on and off for whatever reason we might need.

@task('production:up', ['on' => ['web1', 'web2']])
cd default
php artisan up
@endtask

@task('production:down', ['on' => ['web1', 'web2']])
cd default
php artisan down
@endtask

Migrates the database when necessary. We don't do this in the production:deploy method just for the peace of mind of having a little bit more control over the database. Furthermore it goes through the worker instance instead of one of the web instances and it also uses the --force flag so that it doesn't ask "are you sure you want to migrate in production?". So only use this if you're sure you want to migrate in production.

@task('production:migrate', ['on' => 'worker1'])
cd default
php artisan migrate --force
@endtask

In case you stuff it up.

@task('production:migrate:rollback', ['on' => 'worker1'])
cd default
php artisan migrate:rollback --force
@endtask

A blog about Laravel & Rails by Dwight Watson;

Picture of Dwight Watson

Follow me on Twitter, or GitHub.