January 22, 2014
Up until recently I have been hosting all of my Laravel projects on Pagoda Box. In case you don’t know, Pagoda Box is a PaaS which makes deploying your php apps a breeze. Pagoda Box is seriously great, and has served me well up until now, but for a number of reasons which I will outline below, I have decided to take the VPS route.
Hands down the best feature of Pagoda Box is the git deployment, which allows you to deploy your site simply by pushing to the remote repository, and then a new web instance is automatically created, and database migrations made etc.
After using git deployment for so long, I really couldn’t go without it, so after a little bit of searching I came across an open source project called Dokku, which makes creating your own platform as a service relatively simple.
Why a VPS?
Like I said I have nothing against Pagoda Box, and would seriously recommend to anyone who wants a simple and easy hosting platform, but for me there were a number of reasons it will no longer work:
- No PHP 5.5 support (Although I am aware a private beta is currently in progress supporting PHP 5.5)
- No root access. This is quite a big one for me as it means there is no way to run you artisan commands after deploy. Of course we can work around this but it is not ideal.
- Price – I’m a student, I don’t have much cash, and although I think Pagoda Box is worth every penny, I can get a VPS with much better equivelant specs for a fraction of the price. Of course you lose out on easy horizontal scaling using a VPS, but I figure this won’t be too much of a problem for the time being.
Setting up Dokku on Digital Ocean
I chose Digital Ocean as my VPS because I have been hearing great things about them and from what I can see they offer super value for money. Root access for $5 a month is nothing to be laughed at! Digital Ocean actually provide their own tutorial on how to get started with Dokku and PHP apps which you can find here, but following it exactly I had quite a lot of trouble, so instead I have outlined below the steps I required to get everything working.
1. Create Your Droplet
First things first, we need to create a VPS instance with Dokku installed. Of course before doing this you will need a Digital Ocean account. Just a note a quick Google for “Digital Ocean Coupons” will hopefully supply you with $10 credit that you can add to your account after creating it. If you want to be super nice you could use my referral link to sign up too ;). To make ssh a little easier you will probably want to add an ssh key to your account after you have signed up. Details on how to do this can be found here: Setting up ssh keys.
After you have done all the above, create your first droplet from the dashboard. I chose the smallest instance available for the time being as it can easily be scaled later. I also chose a hostname of “Dokku” and Amesterdam as my region, but really this is all personal preference. Next you want to select an image for your droplet. Click on the “Applications” tab and then look for “Dokku on Ubuntu 13.04”.
Finally add the ssh key you created earlier and click create droplet. Within 55 seconds you’ll be ready to go.
By default the Dokku installation on the Digital Ocean isn’t up to date. Before doing anything else it made sense to update both Dokku and Buildstep, a package that handles creating your PHP instances using Heroku builpacks. To do this shh into you new droplet like so:
If like me you chose the 512mb droplet, you will need to create a swapfile otherwise you will run out of ram while trying to install all the bits and pieces. Digital Ocean provide an easy to follow tutorial for this so I will not go into details here.
First we’ll update Dokku using the instructions provided on GithHub:
$ git pull origin master
$ sudo make install
Now I had a couple of issues when performing this the git pull. First I was confronted with an error letting me know I needed to identify myself. This can easily be remedied with the following command:
After fixing that issue I was then presented with another error that caused the pull to fail. This time a merge conflict was to blame. I couldn’t be bothered messing around trying to work out and resolve the conflict, so instead I just forced the pull using the following commands:
$ git reset --hard origin/master
Not pretty but it works!
After that try the make install command again and Dokku should begin to update. Once that has finished I also updated Buildstep following the instructions on the Dokku read me. As far as I remember I had no issues here so hopefully you won’t either:
$ cd buildstep
$ git pull origin master
$ sudo make build
3. Installing the MySQL plugin & creating the DB
The base Dokku install can be extended by using a number of plugins. A complete list can be found here. By default there is no database installed, and as it turns out, the guy responsible for the MySQL plugin appears to gone a bit awol. Installing the plugin MySQL plugin linked on the plugin page results in all kinds of errors. Mainly because it tries to make use of a user that doesn’t exist. Luckily a nice chap has submitted a pull request which appears to fix most of the problems, so we will install that version instead. His repo is here. To install MySQL use the following (make sure you use Banyan’s repo):
$ git clone https://github.com/banyan/dokku-mysql-plugin.git mysql
$ chmod +x mysql/install mysql/commands mysql/pre-release
$ dokku plugins-install
You can verify that the MySQL plugging installed correctly by running dokku help and you should see a list of MySQL related functions:
No we can create the database for our Laravel app. This is a simple process:
If all went well you should see the details of the new db.
4. Preparing for deployment
There’s just a few more steps to follow before we are are ready to deploy. First open your browser and visit your droplet’s ip. You should be greeted by a Dokku config page. You should see your ssh key here. This is important as without it you the server will reject your git pushes. If you want to use a custom domain name, place it in the hostname text field and then point your A records to the droplet’s ip. If you use a custom domain you can also tick “Use virtual host naming for apps”. This will allow you to If all is well click “Finish Setup” and the browser window will close.
Presuming you already have a Laravel app you would like to deploy using Dokku, you will need to make a few alterations to your composer.json file before things work. This is based of a gist here. Sorry about the formatting here, can’t seem to get indents working!
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"php artisan optimize",
"chmod -R 777 app/storage"
"chmod -R 777 public",
"php artisan migrate"
"php artisan clear-compiled",
"php artisan optimize"
"php artisan key:generate"
The important parts here are within post-install and extra. In post install we set the permissions of both the public and storage folders allowing Laravel to write to them, and we also call php artisan migrate. This means that whenever you deploy, database migrations will also be run automatically.
In extra we provide information that is required by Buildstep, the package that puts together your virtual web instance. Without this, when you push to the remote server the type of app you are deploying won’t be recognised. Don’t worry about the silex bit.
You will also need to update your Laravel database.php config file to make use of the database you created a while back. If you have forgotten what these were you can find them easily again like so:
5. All systems go!
Ok so we are almost ready to deploy. I’m presuming your local Laravel is already being tracked with git. Make sure that you have a composer.lock file and that it isn’t being ignored in you git repository. Without the lock file being pushed too buildstep will not select a builpack. If you don’t appear to have a composer lock file, run composer update and one should be generated. Commit the changes you made to database.php and composer.json. Then we need to add a new remote repository, so open another terminal window and cd to you local repository and do the following (make sure the app name is the same as the one you used earlier for the database creation):
Now you can push!
If everything goes well you should see a response from the server in your terminal window, and you should be able to track the build’s progress.
At this stage I had one final issue. The push was failing because of this error:
After a bit of snooping around on Github this error can be fixed easily by running the following command in you ssh session:
Now run the push again and fingers crossed your app should be deployed. The output from the push should present you with your app’s url. If everything worked correctly you now have your own Pagoda Box or Heroku for a fraction of the cost.
From now on every time you push to the Dokku repository, Dokku will create a new Docker container to hold your app while keeping the previous version live until everything is ready to be swapped over without any interruption. FYI Docker is the underlying technology that Dokku uses to make all this possible, you can find out more about it here: www.docker.io
I realise this has been more of a haphazard rambling than a proper tutorial, but I hope someone will find it useful. I am pretty new to this sort of thing too, and have probably made mistakes along the way so if anyone else has experience with Laravel and Dokku it would be great to share your knowledge.
Likewise, if you give this a go and come across any other problems I’ll do my best to help out.