Archives

Dokku + Laravel on Digital Ocean

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.

2. Updating

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:

$ ssh root@[yourDropletIp]

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:

$ cd ~/dokku
$ 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:

$ git config --global user.email "johndoe@example.com"

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 fetch --all
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:

$ git clone https://github.com/progrium/buildstep.git
$ 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):

cd /var/lib/dokku/plugins
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:

$ dokku help

No we can create the database for our Laravel app. This is a simple process:

$ dokku mysql:create yourappname

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!

{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"require": {
"laravel/framework": "4.1.*"
},
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
]
},
"scripts": {
"post-install-cmd": [
"php artisan optimize",
"chmod -R 777 app/storage"
"chmod -R 777 public",
"php artisan migrate"
],
"post-update-cmd": [
"php artisan clear-compiled",
"php artisan optimize"
],
"post-create-project-cmd": [
"php artisan key:generate"
]
},
"config": {
"preferred-install": "dist"
},
"extra": {
"heroku": {
"framework": "silex",
"document-root": "public",
"index-document": "index.php"
}
},
"minimum-stability": "dev"
}

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:

$ dokku mysql:info yourappname

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):

$ git remote add dokku dokku@yourdropletip:yourappname

Now you can push!

$ git push dokku master

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:

dial unix /var/run/docker.sock: permission denied

After a bit of snooping around on Github this error can be fixed easily by running the following command in you ssh session:

$ usermod -aG docker dokku

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

Wrap Up

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.

Posted in Laravel Tutorials

  • hey,

    every time i tried to deploy the app, i got this message :
    “Unable to select a buildpack”

    am not sure if you faced something like that, i solve it by deleting the `compose.lock` file from gitignore file, but am still not sure if thats really the case or not ..

    did you got anything like that ?
    thanks

    • Ah yes I think I did come across that issue actually! Yes the composer.lock file is crucial to Buildstep selecting the right build pack for you app so it needs to be tracked. Did you get everything working after that?

      • actually yes, after removing the composer.lock from gitignore, everything worked like a charm ..
        i think you should just put a note in your nice article about it ..

        • Great, glad you got it working. Yes I’ll add a comment to the post like you suggest 🙂

  • jimforcy

    Thanks, this was really helpful Josef.

  • How do you view your nginx logs or PHP logs since they are running in a container?

    • Hi, so it is actually a piece of cake. You can just use the command dokku logs and you should see your logs. If you add -t to the end of that you should get a live tail.

      For the Laravel logs themselves I am actually using the external service Papertrail which is really great.

      • dokku logs for nginx and php doesn’t seem to log to stdout for me, so without using a third party like Papertrail, you could be left with hours trying to work out what your problem is.

        • Yeah I agree logs are a bit of a pain without a service like Papertrail (although Papertrail has a nice free tier), but this is a problem with other PaaS like pagoda box too. You loose your app logs on every deploy.

          A quick google turned this up which might help you out: https://github.com/sehrope/dokku-logging-supervisord

          • Thanks I will have to check that out at some point.

  • Ben Morgan

    Hey there,

    When I run `dokku mysql:create app_name` I get:

    mkdir: cannot create directory ‘/home/git’: Permission denied

    I’ve tried sudo and a few other tricks, but I can’t figure it out.

    ~ $ ls home
    dokku

    I can make a directory in home myself and call it git, but I just don’t know why its not doing it from the mysql command.

    • Greg Blass

      I’m running into the same issue.

  • Tekeste Gebreanenia

    great post worked like a charm!

  • chmod-ing to 777 is probably not a good idea, its a good practice to chmod those directories to 775.

  • Masterarts

    You mentioned a nice way to do it. I also agree with Flawid D’Souza suggestion. I personally don’t like doing complex stuff so I have deployed my laravel apps on Cloudways digitalocean hosting where things were done in few steps avoiding coding.