Deploy Your PHP Application to Bluemix

Deploying to the cloud can save so much time and hassle with commissioning and setting up servers, it’s no surprise that we’re seeing many more organisations take this approach for some or all of their web properties. In this post we’ll take a standard PHP application and deploy it to Bluemix.

You’ll learn how to:

  • prepare your project for the cloud
  • put the databases or other storage elements in place
  • safely convey your work to its new home

The example application here is a simple web-based Guestbook which every self-respecting website had once upon a time (about 20 years ago!). All the code for the project is on GitHub to make it easy to look at the examples here in the context of a real project. The Bluemix platform offers a 30-day free trial so you have a chance to try deploying your own application before handing over your credit card details.

Prepare for Cloud

When we deploy a PHP application, Bluemix automatically realises it’s a PHP project and uses the PHP buildpack to run it. The “buildpacks” are a Cloud Foundry term, meaning a collection of tools needed to run a particular tech stack. The PHP buildpack provides PHP with a selection of extensions and Composer already included. You can also specify other, non Bluemix, buildpacks available for Cloud Foundry if you want, and they’re used (specify this in the manifest.yml which we'll cover later on. Keep reading!).

In contrast to a server where we choose which version of PHP to install, the buildpacks typically support multiple versions of PHP so we need to indicate which one this project should use by specifying this in composer.json if it's not already there.

For my project, I needed to add this line to the require block in composer.json:

"php" : ">=7.0",

This lets the buildpack know what my PHP dependency is, along with my other project dependencies since Composer runs when we deploy the application.

The other change we need to make, is to specify where the webroot should be. We add this information to a file called .bp-config/options.json, which the buildpack automatically reads. There's a number of options that you can configure in this file, but we'll stick with the webroot for now. I set my webroot to the directory public/ which is where index.php is:

Now that the PHP is ready, we move on to putting in the dependencies that the rest of the project needs.

Get Ready to Bluemix

At this point, it’s time to install the tools needed to work with Bluemix:

  • Cloud Foundry (cf)provides all the commands you need to build and manage your app.
  • Bluemix CLI is useful for platform-specific tasks like managing regions, spaces, Bluemix virtual machines, and your account.

These tools have a lot of overlap; everything we do today we can achieve with the cf command alone, however the bluemix tool has some bluemix-specific additions which you may find useful as your own projects grow. Once the commands are installed, we can create the services that our application depends on. Mine needs the Cloudant NoSQL database and RabbitMQ; if yours uses PostgreSQL or MySQL instead, or indeed any of the other services, the process will look pretty similar.

You’ll need your Bluemix account details handy at this point — sign up for the free trial if you don’t already have an account.

Before we can deploy an app to Bluemix, we need to create a space for it to deploy into. There are a few steps to this since Bluemix has multiple regions, organisations, and users, as well as spaces — which makes it really easy to be very organised with large applications but for our first PHP deployment might feel a little bit heavy I admit!

  1. Pick a region and set the API endpoint, e.g. for US South use bluemix api https://api.ng.bluemix.net
  2. Now log in using the command bluemix login. You'll be prompted for your username and password.
  3. Check the list of organisations in your account with cf orgs and switch to the one you want to use by doing cf target -o [org], replacing [org] with the organisation name you want.
  4. Create a new space to deploy to: cf create-space Dev and target it cf target -s Dev
  5. Verify that this all made some sense by doing cf target and make sure that your user, organisation and space settings are as you expect.

We made it! The tools are ready, so we’ll go ahead and set up the services that my application needs.

Commission the Services for Your App

My application needs two services: a Cloudant NoSQL Database (the Bluemix name for CouchDB the awesome document database) and RabbitMQ (no fancy names there). Before I deploy, I will use the cf tool to create these services so that my application can use them.

First up, I’ll create the Cloudant service. The cf help create-service command tells me that I need to specify the service, the plan and then name my service. To find out the exact service and plan names, use the command cf marketplace (beware it can take quite a long time to return as it has a lot of information to find!). For me, the command is:

cf create-service cloudantNoSQLDB Lite guestbook-db

Now when I run cf services I can see the database listed there. You can also see it by going to your Bluemix dashboard in the correct region/organisation/space combination. For most services, you can access their administrative interfaces from here.

To set up RabbitMQ, I enter the following command:

cf create-service compose-for-rabbitmq Standard guestbook-messages

Again, cf services shows my new addition and at this point I have the pieces my application depends on.

Be careful with your create-service commands. Both the services and the plans are case sensitive which can trip you up very easily! If you see errors, double-check you have everything spelled correctly, including case.

There are two next steps: create a manifest file to describe how to deploy the application, and change the PHP code to know how to access these services we just configured using the Bluemix environment variables. We’ll do the manifest file next but if you were thinking there is a missing link, you’re definitely keeping up! On we go …

Create the Manifest File and Deploy

You usually describe how to deploy an application with a manifest file called manifest.yml. If you looked at the GitHub project, you can see that this application has other applications (and a dev platform setup) in addition to this PHP application. I'm putting my manifest file in the directory that contains just this PHP application, which is a couple of levels down from the root of the project, so here we're working in src/web.

My manifest file simply names my application, allocates it some RAM, and states which services it needs available to it. Here it is:

This contains all the information that Bluemix needs to run my application. (The application name must be unique across the whole of the bluemix region, so you need to change the name in your version of this file.) Now we’re ready to deploy. The moment of truth: run cf push to deploy your application to the cloud ...

Hopefully that all worked well, and you see your application working through its deployment steps, installing any dependencies. Eventually you see an information block including a urls field. Go to that URL and you should see your project. In fact, you'll probably see an error message from your project because we didn't explain to PHP how to connect to the services we made earlier on, so we'll deal with that next.

Handy Commands

This seems like a good time to share a couple of commands that I use a lot when setting up an application for the first time:

  • cf logs --recent guestbook-web shows the last few lines of the logs from your application, including its deployment. If there's a syntax error in your PHP application, you'll see it here. You can also use just cf logs guestbook-web to see the logs as they happen (replace with your own application name as appropriate).
  • cf env guestbook-web shows the environment variables available to your application, and since we're about to connect our PHP to the services we created, this is very handy indeed! In particular we'll be looking at the VCAP_SERVICES environment variable as it contains the information about the services that this application has access to.

I made my own quick reference card for keeping track of the commands, so feel free to check that out as you go along too!

Connect PHP to Services

From using the cf env command in the previous section, you can hopefully already see the data you need to plug your PHP application in to its services by accessing the VCAP_SERVICES variable. It's JSON-encoded so in PHP, I use this line to get the configuration into an array I can use:

Once you have this, feel free to use var_dump or something to look at the structure, but essentially there's an array element per service type, with an array element inside for each actual service of that type. We need to amend our existing application so that when we detect we're running on Bluemix, we use the Bluemix variables, and otherwise we fall back to whatever our usual configuration process is. For instance, my example app connects to CouchDB (on the local development platform) or Cloudant (on Bluemix) with a block of code like this (from config.php):

The RabbitMQ setup is a bit more complicated since it uses a certificate and the RabbitMQ library I’m using (php-amqplib) expects the parameters all separate whereas Bluemix sends a complete URL with them already assembled. So the code for connecting to RabbitMQ looks like this (also from config.php):

Looking at this RabbitMQ configuration code, you can see that we first grab the contents of the VCAP_SERVICES environment variable, but then we need to grab the URL for the RabbitMQ service. Once we have it, we break it apart using parse_url() to get the arguments we'll need later to construct the RabbitMQ connection. The path piece has a leading slash on it which we don't need, so the substr() function sorts that out for us. We also need to grab the certificate needed for the SSL connection.

(If you are deploying to Bluemix and using RabbitMQ, take a look in the dependencies.php file in the GitHub project for where the AMQP objects are actually instantiated. There are a couple of extra options to set that might help you succeed.)

Run PHP in the Cloud

The joy of the cloud is that you can just create new applications (and clean up those you don’t need any more) without ordering hardware, installing servers, or keeping up with patching. I’ve found that PHP applications are pretty happy on these cloud platforms and having this sort of setup lets the apps cost as little as necessary but scale as much as demand dictates — capacity planning is a hard problem and it means not having spare servers “just in case”. I hope that by sharing my steps above, I’ve shown you what you need to get your own PHP application into the cloud, and perhaps convinced you to give it a try.