Deploying WordPress with Capistrano

So you’ve been through the first two parts of the series and if not, here’s part 1 and here’s part two. In this third part we’ll go over backing up and restoring your WordPress database via Capistrano tasks and we’ll finally see how to attach our backup task to the main deployment task for automatic backups during deploys.

Getting Started & Recap

In the second part we covered staging servers and tagging, today we’ll leave off where we left — a deploy.rb file along with two staging files which we called production.rb and playground.rb in a directory called deploy right next to our main deployment script.

The two staging scripts don’t differ much from each other, they simply define different variables that are used later by Capistrano. Since we’ll be working with the database today I assume you use different credentials for different servers.

Let’s go ahead and define them individually for production.rb and playground.rb as variables, somewhere at the top of your playground script:

# Database credentials for playground.rb
set :db_database, "playground_database"
set :db_username, "playground_username"
set :db_password, "playground_password"

If you’re using different hosts you can also define a :db_host. Do the same for your production script with the MySQL credentials used on your production server, and as soon as that is done you’re ready to go.

Backing Up MySQL with Capistrano

In the first two parts of this series we worked mostly with code snippets that are executed by Capistrano’s existing tasks by using hooks. Today we’ll do something new — we’ll create our own Capistrano tasks for backing up and restoring the MySQL database. We’ll call them mysqlbackup and mysqlrestore and put them into the deploy namespace, so they’ll be invoked like this from the command line:

cap deploy:mysqlbackup
cap deploy:mysqlrestore
cap production deploy:mysqlbackup
cap production deploy:mysqlrestore

You can change the naming afterwards if you would like to. Before we start scripting, let’s think of what we want to achieve with our backup task: run a mysqldump command and store the output in the backups folder in our Capistrano shared path.

Don’t confuse “shared” with “publicly visible”, shared in Capistrano terms means data which is shared across all releases, not visible to the website visitor. So yeah, log on to your playground and production servers and create that backups folder inside the shared path. That’s where we’ll stick all our database dumps, and as soon as you’re done edit your deploy.rb script and somewhere after all the variables have been defined (or at the end of the script) type this:

namespace(:deploy) do
  desc "Backup MySQL Database"
  task :mysqlbackup, :roles => :app do
    run "mysqldump -u#{db_username} -p#{db_password} #{db_database} > #{shared_path}/backups/#{release_name}.sql"
  end
end

As you can see we created a new task called mysqlbackup inside the deploy namespace. We also gave it a description with desc which then shows up when you ask Capistrano for available tasks with cap -T. The run command is quite simple where you can see the usage of the database credentials variables that we defined in production.rb and playground.rb. If you’re new to mysqldump here’s some help. The release_name variable will contain a timestamp which is used as the filename of the database dump.

So yeah, nothing fancy, go ahead and save your script, then ask Capistrano to execute it on your playground server, like this:

cap deploy:mysqlbackup

You can see from Capistrano’s output log or log on to your server to find your new database dump file there in the backups directory. That’s about it! The second piece of the puzzle is restoring your database and it’s a little more complicated than this ;)

Restoring MySQL with Capistrano

The scenario for a database restore is a little bit more complicated than backing up. Ultimately we’d like to give a list of available backups stored on the server and have the user select which one they’d like to restore.

Capistrano ships with a capture function which lets us execute things on server (a file listing in our case) and capture the output back to our script. Then with a few string manipulations we can tell Capistrano to output some stuff to the console. Here’s the full restore task which you can put underneath the backup one.

namespace(:deploy) do
  desc "Restore MySQL Database"
  task :mysqlrestore, :roles => :app do
    backups = capture("ls -1 #{shared_path}/backups/").split("\n")
    default_backup = backups.last
    puts "Available backups: "
    puts backups
    backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] "
    backup_file = default_backup if backup.empty?

    run "mysql -u#{db_username} -p#{db_password} #{db_database} < #{shared_path}/backups/#{backup_file}"
  end
end

So first we execute a ls -1 command in the backups directory on the server, that will give us a list of available files (and folders) in that path. We set the default_backup to the last backup filename from that list (since it’s the newest one) and then print the available backups with puts.

We then use Capistrano’s CLI.ui.ask method to question the user on which backup they’d like to restore giving a default option. Similar with the tag selection covered in the previous part of this tutorial series.

Finally we execute a mysql command on server, providing it with the MySQL credentials and feeding it our chosen backup file from the backups directory in our shared path. Quite easy, eh? Here’s how you call the MySQL restore task from the command line:

cap deploy:mysqlrestore

Capistrano MySQL Restore

If you changed your mind after launching the restore task you can always press Ctrl+C to stop the Capistrano script.

Backing Up Automatically During Deploy

This is quite a good technique indeed. You can now attach your MySQL backup task to the deploy task so that it’s carried out automatically after a deployment has been done. And all that with one single line at the end of your deploy script:

before "deploy:symlink", "deploy:mysqlbackup"

The deploy:symlink task is the one that points the current directory to latest release after a successful deploy. So right before switching our web server to the new application we’re performing a quick MySQL backup. That’s it. Every time you’ll deploy, Capistrano will now automatically backup your database for you.

I wouldn’t recommend automatically restoring a database during deploy:rollback though ;)

Conclusion

This brings us to the end of the third part in the series. Today we’ve covered tasks basics in Capistrano. We have created two tasks to backup and restore your MySQL database (using variables from your multistage files) and we have also looked at how we can use Capistrano’s capture function to grab data from your servers and use it in your deployment scripts.

Hope you enjoyed it and learned something new. If you have any questions or comments, feel free to use our comment form below. Thanks for stopping by and stay tuned for more!