web dev & more!

Deployments w/Deployer

Published: October 9, 2017

In keeping with my previous posts discussing deployments with Git and Capistrano, I thought it appropriate to mention the latest tool I’ve been using to automate shipping code; Deployer. Since discovering Deployer, I’ve dropped Capistrano and git deployments. Those tools were fine, and if you’re developing with Ruby, I’d encourage you to stick with Capistrano but since I’m doing most of my development with PHP, it only makes sense to use something that was made for PHP and can be easily installed alongside all of my other dependencies with Composer.

So what do you have to do to get started deploying your PHP code quickly, easily, and securely? Let’s dig in.

Installation

There are a few ways to handle this: 1) install Deployer globally with a curl/wget request, 2) install using composer on a per project basis, or 3) install globally with composer. If you install globally, Deployer will function in the same way a global composer install works. That is, you’ll download a .phar archive, move that .phar archive into a directory where it can be run that works with your environment’s PATH, and make that it executable.

curl -LO https://deployer.org/deployer.phar
mv deployer.phar /usr/local/bin/dep chmod +x /usr/local/bin/dep

That’s all you have to do for a global install of Deployer. Otherwise, you can install with one simple line using composer.

composer require deployer/deployer for per project basis or composer global require deployer/deployer for the global composer install.

If you did the curl request, Deployer should work using the command “dep.” If using composer, it’ll probably be “php vendor/bin/dep” but this can be corrected for by creating a quick alias in your system’s .bashrc file that looks like so:

alias dep='php vendor/bin/dep'

Usage

Once we have Deployer installed, we can use it by navigating to our project’s root directory. In there, type dep init to create a deploy.php file. We’re going to modify ours so that it looks similar to the one below. Feel free to use as needed.

<?php
namespace Deployer;

require 'recipe/common.php';

// Project name
set('application', 'PROJECT_NAME_HERE');

// Project repository
set('repository', 'YOUR_GIT_REPO_HERE');

// [Optional] Allocate tty for git clone. Default value is false.
set('git_tty', true);

// Shared files/dirs between deployments
set('shared_files', []);
set('shared_dirs', ['vendor']);
set('keep_releases', 5);

// Writable dirs by web server
set('writable_dirs', []);

// Hosts
// live is the alias of the server, this would come in handy
// when specifying which server to deploy if I had another to include

host('live')
-&gt;hostname('DEPLOY_TO_THIS_SERVER')
-&gt;user('USER_TO_DEPLOY_AS')
-&gt;identityFile('~/.ssh/id_rsa')
-&gt;set('deploy_path', 'PATH_TO_DEPLOY_TO')
-&gt;set('composer_options', 'install --no-dev')
-&gt;set('branch', 'master');

// Tasks

// This is sample task that I've included to show how simple
// it is to customize your deployer configuration. For now,
// it just needs to be declared and we'll call it later.

// Runs database migrations using a package called Phinx (post to come later)
desc('Phinx DB migrations');
task('deploy:migrate', function () {
run('cd {{release_path}} &amp;&amp; php vendor/bin/phinx migrate -e live');
});

desc('Deploy your project');
task('deploy', [
'deploy:info',
'deploy:prepare',
'deploy:lock',
'deploy:release',
'deploy:update_code',
'deploy:shared',
'deploy:writable',
'deploy:vendors',
'deploy:migrate',
'deploy:clear_paths',
'deploy:symlink',
'deploy:unlock',
'cleanup',
'success'
]);

// [Optional] If deploy fails automatically unlock.
after('deploy:failed', 'deploy:unlock');

This file should be pretty self explanatory so I won’t go through it line by line but notice there are a couple of things that should be pointed out. Firstly, the shared directories are useful so that on my production server, I don’t have 5 different vendor folders that need to be installed every time I deploy. Next, I’ve specified an alias for my server and called it live. That makes running the deployment command very simple and gives me the option to specify which host to deploy to, should I need to add another host. Thirdly, I’ve specified that for this host live, I should run composer with the --no-dev flag so that dependencies like Deployer aren’t installed. And finally, my custom task deploy:migrate is called after the deploy:vendors. This doesn’t necessarily need to be called here, but it does need to be called after deploy:update_code as that is the task that will pull my code from the git repo, and I don’t want to be running and older version of the migrations.

Launch!

Now what? Deploy! Just kidding, there is actually one other thing you should check before you deploy. Some services like Bitbucket, require that your production server can pull down your git repo. You may need to create an SSH key on your server and add the public key to your git repo’s access keys. Check your repo’s settings to make sure your server can pull code from there.

Now, you can launch and it’s as easy as dep deploy live. Assuming you’ve pushed all of your code to your repo, you should see the latest version running on your server!