Deploying Laravel 5 application to Heroku

This explains how to deploy a Laravel 5 application to Heroku with additional support for Gulp and Bower to use with Laravel 5's Elixer. This assumes that you already know how to use Gulp and Bower.

What is Heroku

Heroku is a cloud platform as a service (PaaS) that is built around the hosting and deployment of web-based applications. While it can host content-based websites, it is primarily designed around scalable applications; from one-pagers to enterprise.

The benefit of Heroku is that it allows you to host prototypes and applications that are in development with very little traffic/use for FREE.

Requirements

  1. PHP 5.4 support
  2. Heroku supports Postgres(PSQL) out of the box. Additional configuration is needed if you insist on using MYSQL. Be sure to plan accordingly. IMPORTANT!
  3. Project is under GIT version control

Steps to deployment

1. Setup Heroku

NOTE: If you have used Heroku before, skip this step.

Assuming that you have never worked with Heroku before, you will need to download the Heroku Toolbelt for your respective operating system. Once installed, go to heroku.com and create an account and verify your email address if necessary. Next open up your terminal/CLI and type the following command:

heroku login

This will ask you for the username and password for the account that you just created. Assuming that your credentials are correct, you should receive a success message. Now you are logged in.

2. Create a Project

After authenticating our user, we now need to create an application. To do so, use the following command:

heroku create [app-name]

Replace [app-name] with your application name. Be sure to NOT use spaces or special characters. It should be like a URI slug in nature. Also the name that you give your application has to be unique to Heroku. If it fails, try try try again. After a successful name has been selected, Heroku will add an addition remote branch to your repository.

3. The Procfile

The Procfile is a special type of configuration file that is unique to Heroku. It allows you to customize your server settings like you would for Apache or NGINX. Since Laravel uses the public directory to serve its routes, we need to tell Heroku to target this directory. To do so create a new file titled Procfile. NOTE, do not add any preceeding or trailing prefixes or punctuation. This will prevent it from working. Next add the following line to your newly created Procfile:

web: vendor/bin/heroku-php-apache2 public/

Once finished, save the file and close it. We won't need to do anything else.

4. Buildpacks

Buildpacks within Heroku tell the system what type of code-sets your application uses to serve its content/functions. Heroku will then in turn look for your dependency listings to install the necessary dependencies. More often than not, you will only need one buildpack. However if you use the built-in Elixer gulp task to compile your SASS/LESS and other front-end dependencies, additional configuration is needed.

First we need to install a buildpack that tells Heroku that we want to use multiple buildpacks. [The repository can be found here](heroku buildpacks:set https://github.com/ddollar/heroku-buildpack-multi.git). To install it, type the following command:

heroku config:set BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git

This will set a configuration variable (these will be touched on later) and will install the buildpack. To verify that it was installed, use the following command:

heroku buildpacks

You should see something like the following if it was installed correctly:

=== [app-name] Buildpack URL
https://github.com/ddollar/heroku-buildpack-multi.git

By installing this buildpack, we have now enabled our application to utilize a .buildpack file. Within this file, you can list out the buildpacks you would like to use with your application deployment. To include the buildpacks we need specific for this project, add the following lines:

https://github.com/heroku/heroku-buildpack-nodejs
https://github.com/heroku/heroku-buildpack-php

This tells Heroku that we will need to look for the composer.json and package.json files and then execute both the composer install and npm install commands respectively. Save the file and then close it.

5. package.json Configuration

To ensure that Gulp and Bower work correctly within the Heroku "production" environment, we will need to modify our dependency listing within our package.json. Assuming that you haven't changed your package.json from the default Laravel install, it should look like this:

{
    "private": true,
    "devDependencies": {
        "gulp": "^3.8.8"
    },
    "dependencies": {
        "laravel-elixir": "^3.0.0"
    }
}

If we were to deploy this, Heroku would not be able to run the Gulp or Bower commands becuase they are not listed as dependencies. We will need to update our package.json to look like this:

{
    "private": true,
    "devDependencies": {
        "gulp": "^3.8.8"
    },
    "dependencies": {
        "laravel-elixir": "^3.0.0",
        "gulp": "^3.8.8",
        "bower": "^1.5.2"
    },
    "scripts": {
        "postinstall": "bower install && gulp --production"
    }
}

As you can see, both Gulp and Bower have been add as production dependencies. Also a new scripts object has been added with a line titled "postinstall." By adding this object, npm (Node Package Manager) allows us to run shell commands after the dependencies have been installed. In this case, the application will be installing the necessary Bower packages and the executing the production Gulp task.

NOTE: The Production Gulp task is just like the normal gulp task, but it also minifies the code. This will help with performance.

6. Database

One of the other benefits of Heroku is that it packages many common services/packages and offers them as addons. What is different about these is that you do not have to worry about security updates and patches; Heroku handles everything.

As noted earlier, Heroku offers Postgres support out of the box. For the sake of this example, that is what we are going to use. To set up a Postgres database for this project, enter the following command:

heroku addons:add heroku-postgresql:dev

This will tell Heroku to add an addon to this application. In response Heroku will give you some disclaimer text followed by telling you that Heroku set a database URL environment variable. This URL is a Postgres url string that when parsed tells the database server credentials like the username, password, etc.

Next we need to add a special database configuration especially designed to handle this Postgres url. Within the config/database.php configuration file, paste the following code within the 'connections' array:

'heroku' => [
    'driver'   => 'pgsql',
    'host'     => parse_url(getenv("DATABASE_URL"))["host"],
    'database' => substr(parse_url(getenv("DATABASE_URL"))["path"], 1),
    'username' => parse_url(getenv("DATABASE_URL"))["user"],
    'password' => parse_url(getenv("DATABASE_URL"))["pass"],
    'charset'  => 'utf8',
    'prefix'   => '',
    'schema'   => 'public',
],

This configuration parses the DATABASE_URL environment variable and then assigns it to the varying associative array values. Once done, save the file and close it.

7. Environment Variables

As this tutorial has already briefly touched on this; environment variables are global constants that can have string/integer values assigned to them to be used elsewhere within the application. The concept is exactly the same if you utilize the .env file within the Laravel application. Again assuming that you have not added any additional packages that require configuration, we need to set the following environment variables:

APP_ENV
APP_KEY
APP_URL
DB_CONNECTION
MAIL_USERNAME
MAIL_PASSWORD

To set a variable with a value, enter the following command:

heroku config:set APP_ENV=production

Go through each variable that is listed above and set a value. Please note the following variables:

  • DB_CONNECTION - This should be set to 'heroku' as that was the name of the new database configuration that was setup in the previous step
  • APP_KEY - This should be a unique key to secure the hashed values within the application. This website offers random "CodeIgniter Encryption Keys" for free. One of those keys will work nicely.
  • APP_URL - The public facing url of your application (ie http://myname.com)

At any given time, the entire list of set environment variables can be viewed either in your account dashboard on Heroku's website or via your shell with this command:

heroku config

8. Commit & Push

NOTE: If the composer.lock file that was automatically generated by by Composer is currently listed within the .gitignore file, remove it. Heroku requires the composer.lock file to be present during deployment.

At this point we can commit all (or individually) of the changes that we have made and then push them with:

git push heroku master

Git will now push all of your code and configuration up to Heroku. If this is the first time this has been done, the entire deployment process can take a while. This is because after the initial deployment, if the buildpacks and other dependencies have not changed, Heroku will cache them to speed up the deployment process in the future.

9. Clean-up

Assuming that there were no issues during your deployment (if there were, debug as necessary), Heroku will give you a success message within your shell window. But we are not finished. If you can recall all that we have done with the database, while it has been installed and configured, the migrations have not been run. To do this, we will use the heroku run command in conjunction with the normal Artisan commands. The heroku run command allows you to run shell commands remotely from your machine. So to migrate your database, enter:

heroku run php artisan migrate

Assuming no errors, you can now run your databse seeding (if available):

heroku run php artisan db:seed

10. Finished

Now that everything has been migrated, we can now view the application by entering the following command:

heroku open

This will open a new browser window. It is worth noting that Heroku by default shows all of these windows using the HTTPS prefix; which may cause issues with your images and stylesheets. Simply change it to HTTP and your page should return to normal.

THAT'S IT