How to deploy PHP/MySQL web application with several external dependancies, across multiple Linux platforms

If you would create a deployment system for PHP/MySQL web application with several external dependancies, across multiple *nix platforms usually you can use rsync or may be scp, git, and pear for dependencies and some custom scripts.

In the fact, there are a nice solution and interesting one based on three tools : capistrano, jenkins and composer

Capistrano to deploy project to remote servers and be able to rollback when screw up.
Capistrano is a nice ruby application that can perform pre and post-deploy functions like restarting webserver, busting cache, renaming files, running database migrations, with capistrano we can easily copy code from source ( control repository ) to production server.

Capistrano by itself isn’t enough to make my deployment complete, that why my capistrano script will runs composer on the app to gather dependencies.

First , you can get capistrano using gem like that:
sudo gem install capistrano
sudo gem install capistrano-ext

You may get composer using git like this, run :
git clone https://github.com/composer/composer.git

In general, you’ll use Capistrano as follows:

You will create a recipe file (“capfile” or “Capfile”) usgin capify command line as follow :
capify .
This will create config directory and a deploy.rb file that we will edit
vim confing/deploy.rb

deploy.rb is ruby file with a very simple syntax, here is my recipe file that i use to deploy my blog:



set :application, "blog"
#You probably want to change this to be the location of the repo you just forked
set :repository,  "git://github.com/WordPress/WordPress.git"

set :php_bin, "/usr/bin/php"

#The following is not the document root, but just the app root 
set :deploy_to, "/home/mezgani/www/#{application}/"

set :current, "/home/mezgani/www/#{application}/current"

role :web, "server1", "server2"                          # Your HTTP server, Apache/etc
role :app, "server1", "server2"                          # This may be the same as your `Web` server
role :db,  "database-server", :primary => true # This is where Rails migrations will run
role :db,  "database-server"

set :local_path, "/home/mezgani/config/wordpress/config"

# SSH Settings
set :user, "mezgani"
#set :password, "password"
ssh_options[:keys] = %w(/home/user/.ssh/id_rsa) # SSH key
ssh_options[:port] = 22

#########################
#things you'll probably not change, unless you know what you're doing 
###########################
# If you aren't using Subversion to manage your source code, specify
# your SCM below:
# set :scm, :subversion
set :scm, :git

#the following is needed because if it's not there, for some reason we don't get
#asked to accept the key from github..annoying when deploying to a new server
default_run_options[:pty] = true

#since this is PHP, we don't really need to restart apache or anything
set :use_sudo, true 

#ssh agent forwarding..
ssh_options[:forward_agent] = true

#A lot of this stuff has been overridden for PHP/Non Rails magic

namespace :deploy do
  
  task :default do
    update
    finalize_update
    composer
  end
  
  
  task :finalize_update, :except => { :no_release => true } do
    run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true)
    run "cp -fr #{current}/wp-content #{shared_path}/"
    run "cp #{current}/.htaccess #{shared_path}/"
    run "cp #{current}/wp-config.php #{shared_path}/configs/"
    run "cp #{shared_path}/configs/wp-config.php #{latest_release}/"
    run "cp -fr #{shared_path}/wp-content #{latest_release}/"
    run "chmod -R 777 #{latest_release}/wp-content"
    run "cp #{shared_path}/.htaccess #{latest_release}/"
  end
end 

task :composer do
  top.upload("#{local_path}/composer.json", "#{shared_path}/install", {:via => :scp, :recursive => true})
  run "cd #{shared_path}/install && curl -s http://getcomposer.org/installer | #{php_bin}"
  run "cd #{shared_path}/install && ./composer.phar install"
end

task :setup do
  run "sudo apt-get install curl"
  run "mkdir #{shared_path}/"
  run "mkdir #{shared_path}/install/"
  run "mkdir #{shared_path}/configs/"
  
  set(:wp_environment_ready, Capistrano::CLI.ui.ask("Is wp-config.php ready for this environment? (yes/no): "))
  if wp_environment_ready == 'yes'
    #top.upload("htdocs/wp-config.php", "#{shared_path}/configs/wp-config.php", :via => :scp)
    run "cp #{deploy_to}/wp-config.php #{shared_path}/configs/wp-config.php "
  end
  run "mkdir #{shared_path}/wp-content"
  run "mkdir #{shared_path}/wp-content/uploads"
end

Before deploy we have to define a composer.json file that defines all
the dependencies my application has, whether they’re composer enabled or not.

Edit composer.json, specify your dependencies and run composer on capistrano to get the dependencies:
vim composer.json

Finally, use the cap script to execute your recipe. Use the cap script as follows:
cap deploy

How to deploy PHP/MySQL web application with several external dependancies, across multiple Linux platforms

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s