Automating application deployment (a WordPress example)

Chef can also be used to deploy applications from code repositories. It combines one of the most complete, feature rich, and complicated Chef resources available—the deploy resource—and the various powerful and popular cookbooks, such as the database cookbook. We'll show you how to deploy a simple WordPress application right from the GitHub repository, creating a dedicated database and user as well as all the required dependencies. This builds on what has already been done previously, but the resources and cookbook shown here are made to be reusable anywhere.

Getting ready

To step through this recipe, you will need:

  • A working Chef DK installation on the workstation
  • A working Vagrant installation on the workstation
  • The Chef code (optionally) from Chapter 6, Fundamentals of Managing Servers with Chef and Puppet, Chapter 7, Testing and Writing Better Infrastructure Code with Chef and Puppet, or any custom Chef code

How to do it…

As we're going to deploy an application for MySite (maybe an engineering blog for the MySite company), let's call this recipe mysite::deploy. Create the recipe like this from chef-repo:

$ chef generate recipe cookbooks/mysite deploy

Our next steps will be to include the Apache and MySQL dependencies, configure everything on MySQL so that WordPress can be installed, and finally deploy the WordPress code from GitHub.

Including dependencies

A WordPress installation needs at least an HTTP server and a database. Start by including the known dependencies to the service we already have: an Apache virtual host and MySQL. Include them in deploy.rb:

include_recipe 'apache::virtualhost'
include_recipe 'mysite::mysql'

Creating the application's database

Before we deploy anything, we need to create a database on our already running MySQL server with a dedicated WordPress user. There's a wonderful cookbook meant just for this: the database cookbook. We'll reuse this one very often. It gives access to many helpers for most use cases and most types of databases. According to the documentation, we'll need to deploy a gem named mysql2_chef_gem, which fortunately comes with a dedicated cookbook as well. And finally, as we're using MySQL, let's make sure we depend on its official cookbook. Let's include all of this information in our mysite cookbook's metadata.rb:

depends 'database'
depends 'mysql2_chef_gem', '~> 1.1'
depends 'mysql', '~> 8.1'

To build the mysql2 gem using the cookbook's new mysql2_chef_gem resource, we'll need the MySQL development package named mysql-community-devel. Let's add the following to our deploy.rb recipe:

package 'mysql-community-devel'

mysql2_chef_gem 'default' do
  action :install
end

The database cookbook created, among others, two useful resources for us: mysql_database and mysql_database_user. As we can guess by their names, they respectively help create MySQL databases and MySQL users. Let's create the MySQL connection information variable so it can be reused in our two resources:

mysql_connection_info = {
  host: '127.0.0.1',
  username: 'root',
  password: 'super_secure_password'
}

Note

In a proper production environment, we should use encrypted data bags for this matter, as seen in this chapter. We're trying to keep the code simple here.

Now we can create our database named wordpress using the mysql_database resource:

mysql_database 'wordpress' do
  connection  mysql_connection_info
  action      :create
end

Also, create a wordpress_user MySQL user with the password changeme. This will create the user and grant all the privileges to it:

mysql_database_user 'wordpress_user' do
  connection    mysql_connection_info
  password      'changeme'
  database_name 'wordpress'
  host          '%'
  privileges    [:all]
  action        [:create, :grant]
end

At this point, we should have everything we need related to the database.

Deploying an application from git or GitHub

Now on to application deployment! We know we want to deploy from git. Let's make sure git is installed:

package 'git'

The deploy_revision resource is the most complex of all. It has a multitude of options, and a full chapter about it wouldn't be enough. Let's keep it simple here and refer to the complete online documentation for more complex uses. Let's keep it simple here, and please refer to the very complete online documentation for more complex uses—because this resource is absolutely powerful and does wonders when properly manipulated. We know the following:

  • Our code is available at https://github.com/WordPress/WordPress
  • We want to try the latest revision (HEAD) and keep the last five revisions to allow rollbacks
  • Our HTTP web server runs under the apache user
  • The virtual host folder is inherited from an attribute set earlier (/var/www/#{node['sitename']})
  • There's no database migrations to execute with WordPress

The deploy_revision resource is modeled after Capistrano and therefore comes from the Ruby on Rails world. But the concepts still apply to most languages, and it's a good practice in production to create shared folders and symlinks for long-lasting configurations and files. It includes certificates, database configuration files, local assets, and so on. However, to keep the current deployment simple, we won't use these right now, even though you'll probably start looking into it as soon as you'll need it. We'll include the symlinks configuration and initialize them to nothing so the code is already present when the time arises. Here's how all this ties together:

deploy_revision 'wordpress' do
  repo 'https://github.com/WordPress/WordPress'
  revision 'HEAD'
  user 'apache'
  deploy_to "/var/www/#{node['sitename']}"
  keep_releases 5
  symlinks({})
  symlink_before_migrate({})
  migrate false
  action :deploy
end

Once the code is applied, the /var/www/mysite (or whatever name you may have overridden) structure will change a little:

$ ls /var/www/mysite/
current  index.html  releases  shared

There's a current, releases, and shared folder. The shared folder contains everything that will last through the releases, including a cached copy of the current code. The releases folder contains all the stored releases. The current folder is itself a symlink to a specific release, which is the git commit SHA on GitHub (72606bed348e61b6f98318cf920684765aa08b37). Each subsequent release will be identified by its SHA indicating its unique identification and symlinked to current at the end of the deployment process. The number of kept releases is set by the keep_releases integer:

$ ls -ld /var/www/mysite/current
lrwxrwxrwx. 1 apache root 65 Nov 17 02:18 /var/www/mysite/current -> /var/www/mysite/releases/72606bed348e61b6f98318cf920684765aa08b37

Once this code is applied to our node, if we navigate to http://<node_ip>/current/, we'll see the WordPress setup page:

Deploying an application from git or GitHub

To check whether the connection to the database is working correctly, type in all of the information from our Chef code:

Deploying an application from git or GitHub

And, job done! The WordPress installer says, All right, sparky! You’ve made it through this part of the installation. WordPress can now communicate with your database. If you are ready, time now to... run the installer!.

We're now basically able to deploy any WordPress installation from scratch, at will, and in seconds, again and again.

Note

Let's insist again:

Once you're comfortable with this, refer to the deploy resource documentation to discover everything this resource has to offer. It works wonders.

There's more…

With Puppet, there is no deploy resource. However, Puppet Labs is providing a useful module—vcsrepo. With this module, we will be able to deploy a WordPress site from git.

Let's reuse our Vagrant LAMP example in Chapter 6, Fundamentals of Managing Servers with Chef and Puppet. We just need to add the vcsrepo module to Puppetfile (do not forget to run r10k puppetfile install):

mod 'puppetlabs/vcsrepo', '1.4.0'

Now we are ready to modify the main manifest of the box, namely web.pomes.pro, to include the WordPress deployment. First, install the git package:

  package {'git':
    ensure => installed,
  }

Then, create a database for WordPress:

  mysql::db {'wordpress':
    user     => 'wordpress_user',
    password => 'changeme',
    host     => '%',
    grant    => 'ALL',
  }

Also, update our virtual definition to change DocumentRoot:

  apache::vhost { 'web.pomes.pro':
    website => 'web.pomes.pro',
    docroot => '/var/www/wordpress',
  }

And finally, install WordPress from git and give rights to Apache:

  vcsrepo {'/var/www/wordpress':
    ensure   => latest,
    provider => git,
    source   => 'https://github.com/WordPress/WordPress',
    revision => 'master',
  }

  file {'/var/www/wordpress':
    ensure    => directory,
    owner     => 'www-data',
    group => 'www-data',
	recurse => true,
}	

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.97.216