Deploying PHP web applications - challenges & solutions
 
Tim Jackson

Deploying PHP web applications
- challenges & solutions

Tim Jackson

If you're building and supporting a number of individual web applications then rapidly reproducing predictable deployments can become a challenge, especially when distributed across multiple developers and multiple environments. This talk outlines some of the real-world challenges, and introduces an open source tool which can help make your life easier.

Basics of deployment

Things we typically have to do to get a system up and running...

Common challenges

which can easily lead to...

Elements of the solution

Toolset goals

Web Application Deployment Framework (WADF)

WADF basics

and

What are we aiming to achieve?

$ wadf-deploy mywebapp
Do you want to deploy database(s) if relevant? (y/n):y
Checking out svn+ssh://svn@svn.example.com/apps/mywebapp/trunk...
PEAR dependencies found; creating a PEAR installation in pear_local/
	install ok: channel://pear.php.net/Archive_Tar-1.3.3
	install ok: channel://pear.php.net/Structures_Graph-1.0.2
	install ok: channel://pear.php.net/Console_Getopt-1.2.3
	install ok: channel://pear.php.net/XML_Util-1.2.1
	install ok: channel://pear.php.net/PEAR-1.9.0
Installing PEAR dependencies...
	upgrade ok: channel://pear.php.net/Net_URL-1.0.15
	upgrade ok: channel://pear.php.net/HTTP_Request-1.4.4
	upgrade ok: channel://__uri/mywebapp-1.1.0
Setting up database mywebapp on host localhost...
	Deleting existing tables in database mywebapp...
	Deploying new schema for database mywebapp as user myuser...
Deploying webserver configuration...
Deploying scheduled jobs from /home/myuser/mywebapp/crontab...
Running kickstart script /home/myuser/mywebapp/setup.php...
----------- OUTPUT BELOW IS FROM KICKSTART SCRIPT, NOT WADF -----------
Set up initial database content.....................OK
------------------- END OF KICKSTART SCRIPT OUTPUT --------------------
Restarting webserver...
Starting WADF HTTPD instance: [ OK ]
Listening on port 10080 and configured for the following applications:
 mywebapp: (/home/myuser/mywebapp)
   ver=DEVTR:1792
   http://mywebapp.localhost.localdomain:10080
$ firefox http://mywebapp.localhost.localdomain:10080

Did that require masses of configuration?

No, If you use the standard conventions, what we just saw can be done from a default install with only 1 option:

[local]
vc_base = svn+ssh://svn@svn.example.com/apps

Templating (1): macros

Templating (2): specifying defaults

Defaults can be specified in a file called wadf.conf in the root of the site (this can be checked in if you don't include passwords or things that vary from deployment-to-deployment...). Example:

[local]
admin_email = developer@example.com

[staging]
admin_email = qa@example.com

[live]
admin_email = sales@customer.example.net

Templating (3): prompting

If you need to prompt at install time...

[globals]
; Here's a macro with a made-up name
admin_email = developer@example.com

[staging]
; '%%' means "prompt on deploy" (with optional message)
admin_email = %%E-mail address to receive admin notifications
vhost1_name = staging.example.com

[live]
; '**' means "something should have been filled in here; halt the deployment"
admin_email = **Awaiting customer admin contact
vhost1_name = www.example.com

These values get saved in a file called .wadf-instance within the deployment.

Special files

By default, these are all in the root of the application, but that's configurable (as is the naming).

Webserver config

Example vhost.conf.template

<VirtualHost @vhost1_interface@>
	ServerName @vhost1_name@
	DocumentRoot @deploy_path@/webroot
	RewriteEngine on
	RewriteRule /.* @deploy_path@/application/bootstrap_http.php
</VirtualHost>

PHP configuration

Example php.ini:

engine = on
; when processed, 'php_dir' will be the path to the PEAR installation
include_path = .:@deploy_path@/include:@php_dir@
register_globals = off
magic_quotes_gpc = off
...

PEAR dependencies

Create a package.xml file in the root of the site (location configurable)

PEAR dependencies example

Example package.xml for the web application itself:

<package version="2.0" xmlns="http://pear.php.net/dtd/package-2.0"...>
 <name>testapp</name>
 <channel>__uri</channel>
 <summary>Test application</summary>
 <description>Test application</description>
 ...some boring stuff here: version, notes, developer etc. ...
 <dependencies>
  <required>
   <php><min>5.2.0</min></php>
   <pearinstaller><min>1.7.0</min></pearinstaller>
   <package>
    <name>HTTP_Request</name>
    <channel>pear.php.net</channel>
    <min>1.4.4</min>
   </package>
  </required>   
 </dependencies>
 <phprelease/>
</package>

Snapshotting dependencies

PEAR:pear.php.net/Archive_Tar-1.3.3
PEAR:pear.php.net/Console_Getopt-1.2.3
PEAR:pear.php.net/Date-1.4.7
...
SVN:svn+ssh://svn@svn.example.com/Somelib/trunk@12345 /checkouts/Somelib
...

(SVN dependencies are there as an optional alternative to externals; useful if you have groups of developers accessing SVN via different protocols e.g. HTTP, SVN, SVN+SSH etc.)

WADF Installation

Basic configuration

Command line tools

Typical development workflow

  1. Initial deploy of application using wadf-deploy. This will:
    • process all template files (*.template)
    • install PEAR dependencies automatically, including creating a clean PEAR install if required
    • set up a database using schema.sql, if required
    • deploy scheduled jobs
    • run a kickstart script, if defined
    • start a WADF HTTPD server instance (for local workstation)
  2. Make your changes, fix a bug/add a feature
    • Run wadf-reprocess if you've changed any template files or dependencies
  3. Check into SCM
  4. Go to step 1 :-)

Other features include...

Getting involved

www.timj.co.uk/computing/software/wadf