OpenShift, ZF2, and Composer
I was recently shopping around for inexpensive cloud hosting; I want to try out a couple of ideas that may or may not have much traffic, but which aren't suited for my VPS setup (the excellent ServerGrove); additionally, I'm unsure how long I will maintain these projects. My budget for this is quite small as a result; I'm already paying for hosting, and am quite happy with it, so this is really for experimental stuff.
I considered Amazon, Orchestra.io, and a few others, but was concerned about the idea of a ~$50/month cost for something I'm uncertain about.
When I asked in #zftalk.dev, someone suggested OpenShift as an idea, and coincidentally, the very next day Zend announced a partnership with RedHat surrounding OpenShift. The stars were in alignment.
In the past month, in the few spare moments I've had (which included an excellent OpenShift hackathon at ZendCon), I've created a quick application that I've deployed and tested in OpenShift. These are my findings.
ZF2
I didn't really have to do anything different to have
zf2 work; the standard .htaccess
provided in
the skeleton application worked flawlessly the first time (I've worked with
some cloud environments where this is not the case).
The only frustration I had was the default directory structure OpenShift foists upon us:
data/
libs/
misc/
php/
This is not terrible, by any stretch. However, it's attempting to dictate the application structure, which I'm not terribly happy with — particularly as my structure may vary based on the framework I'm using (or not!), and because I may already have a project written that I simply want to deploy.
In particular, the php
directory is galling — it's simply the document root.
Most frameworks I've used or seen call the equivalent directory public
, or
web
, or html
— but never php
(in large part because the only PHP file
under the document root in most frameworks is the index.php
that acts as the
front controller). It would be nice if this were configurable.
This conflicts a bit with how a ZF2 app is structured. I ended up doing the following:
- Removed
php
and symlinked mypublic
directory to it. - Removed
libs
and symlinked myvendor
directory to it. - Removed
misc
as I had no need to it.
Nothing too big, thankfully — but problematic from the perspective of, "I've already developed this app, but now I have to make changes for it to work on a specific cloud vendor."
Composer
My next question was how to use Composer during my deployment process, and some some googling found some answers for me.
Basically, I needed to create a deploy
task that does two things:
- Unset the
GIT_DIR
environment variable. Evidently, the build process operates as part of a git hook, and since Composer often uses git repositories, this can lead to problems. - Change directory to
OPENSHIFT_REPO_DIR
, which is where the application root (not document root!) lives.
Once I did those, I could run my normal composer installation. The deploy
task looks like this:
###!/bin/bash
### .openshift/action_hooks/deploy
( unset GIT_DIR ; cd $OPENSHIFT_REPO_DIR ; /usr/local/zend/bin/php composer.phar install )
This leads into my next topic.
Deployment
First off, as you probably guessed from that last secton, there are hooks for deployment — it doesn't have to be simply git. I like this, as I may have additional things I want to do during deployment, such as retrieving and installing site-specific configuration files, installing Composer-defined dependencies (as already noted), etc.
Over all, this is pretty seamless, but it's not without issues. I've been told that some of my issues are being worked on, so those I won't bring up here. The ones that were a bit strange, and which caught me by surprise, though, were:
- Though the build process creates the site build from git, your submodules are not updated recursively. This tripped me up, as I was using EdpMarkdown, and had installed it as a submodule. I ended up having to import it, and its own submodule, directly into my project so that it would work.
- I installed the MongoDB cartridge. Ironically, it was not then enabled in Zend Server, and I had to go do this. This should be turnkey.
-
/usr/bin/php
is not the same as/usr/local/zend/bin/php
. This makes no sense to me if I've installed Zend Server as my base gear. Considering they're different versions, this can be hugely misleading and lead to errors. I understand there are reasons to have both — so simply be aware that if you use the Zend Server gear, your tasks likely should use/usr/local/zend/bin/php
.
The good parts?
- You can alias an application to a DNS CNAME — meaning you can point your domain name to your OpenShift applications. Awesome!
- Simplicity of adding capabilities, such as Mongo, MySQL, Cron, and others. In most cases, this is simply a "click on the button" and it's installed and available.
- Zend Server. For most PHP extensions, I can turn them on or off with a few mouse clicks. If I want page-level caching, I don't have to do anything to my application; I can simply setup some rules in the Zend Server interface and get on with it, and enjoy tremendous boosts to performance. I used to enjoy taming and tuning servers; most days anymore, I just want them to work.
-
SSH access
to the server, with a number of commands to which I've been given
sudoer
access. If you're going to sandbox somebody, this is a fantastic way to do it. Oh, also: SSH tunnels to services like Mongo and MySQL just work (via therhc-port-forward
command).
Summary
Over all, I'm quite pleased. While it took me a bit to find the various incantations I needed, the service is quite flexible. For my needs, considering I'm doing experimental stuff, the price can't be beat (the current developer preview is free). Considering most stuff I do will fall into this or the basic tier, and that most cartridges do not end up counting against your alotment of gears, the pricing ($0.05/hour) is extremely competitive.