Laravel Quickstart Guide

This guide will show you how to set up a PHP app using the Laravel framework and MySQL or PostgreSQL. This guide leverages Dockerfile Deploy.

This guide is designed for Laravel 5.x and later, although it should work on Laravel 4.x as well.

Create an App

Tell Enclave that you want to provision an App. Until you push code and trigger a build, Enclave uses this as a placeholder.

To create an App, use the Dashboard, or the aptible apps:create command:

# Set or substitute $APP_HANDLE with the app name of your choice

aptible apps:create "$APP_HANDLE"

Enclave will provide your App’s Git Remote in return. Copy it, you’ll need it later.

Going forward in this document, we’ll refer to the App’s handle as $APP_HANDLE, and the its Remote as $GIT_REMOTE.

Provision a Database

Use one of the following commands to provision a 10GB Database, depending on whether you’d like to use PostgreSQL or MySQL:

  • PostgreSQL: aptible db:create $DB_HANDLE --type postgresql
  • MySQL: aptible db:create $DB_HANDLE --type mysql

Make sure you set or substitute $DB_HANDLE with the database name of your choice (alternatively, you could use the Dashboard to create a Database as well).

The aptible db:create will return a connection string on success. This is a Database Credential. You’ll need it later to configure your App.

Going forward in this document, we’ll refer to the Credential as $DATABASE_URL.

Note

Databases are only reachable from within your Stack’s internal network.

This means your Containers will be able to connect to your database, but if you want to connect from your wotrkstation, you’ll need to use a Database Tunnel.

Add a Dockerfile

The Dockerfile is a text file that contains the commands you would otherwise execute manually to build a Docker image. Aptible uses the resulting Image to run Containers for your App.

A few guidelines:

  1. The file needs to be called Dockerfile, starting with a capital letter, and no extension.
  2. Place the Dockerfile at the root of the repository.
  3. Be sure to commit them to version control.

Here is a sample Dockerfile for a Laravel app. This will install your dependencies via Composer, and configure your app public folder to be served by Apache:

FROM quay.io/aptible/php:7.0

WORKDIR /app

ADD composer.json /app/
ADD composer.lock /app/
RUN composer install --no-ansi --no-interaction --no-scripts --no-autoloader

ADD . /app
RUN composer install --no-ansi --no-interaction
RUN chown -R www-data:www-data /app/storage /app/bootstrap/cache

RUN rm -rf /var/www/html && ln -s /app/public /var/www/html

Automate Database Migrations

Finally, your app probably expects you to run database migrations upon deploy to ensure your app code and database are in sync.

You can tell Aptible to run your migrations by adding a .aptible.yml file in your repository.

The file should be named .aptible.yml, and found at the root of your repository (make sure to check it in after creating it).

Here is a sample .aptible.yml file to automate Database migrations:

before_release:
  - php artisan migrate

Teach your app about how to connect to a database on Aptible

When deploying an app on Aptible, you’re encouraged to pass database configuration via environment variables. To do so on Aptible, you’ll need to make a few tweaks to your config/database.php file.

First, add the following function at the very top of the file:

// NOTE: this function *must not* throw exceptions, otherwise Laravel
// will fail to boot. So, instead of throwing exceptions, we just
// return an intentionally invalid (empty) configuration if
// DATABASE_URL is not set.
function generateAptibleConnection() {
  if (getenv('DB_CONNECTION') !== 'aptible') {
    // If the DB_CONNECTION is not Aptible, then this won't be used,
    // and we should just bail out.
    return [];
  }
  $raw_url = getenv('DATABASE_URL');
  if (!$raw_url) {
    error_log('DB_CONNECTION is aptible, but DATABASE_URL is not set!');
    return [];
  }
  $url = parse_url($raw_url);
  $aptibleConnection = [
    'host'      => $url["host"],
    'port'      => $url["port"],
    'username'  => $url["user"],
    'password'  => $url["pass"],
    'database'  => substr($url["path"], 1),
    'charset'   => 'utf8',
    'prefix'    => '',
  ];
  $scheme = $url["scheme"];
  if ($scheme === "mysql") {
    // NOTE: The options below are required to run on Aptible, because
    // Aptible enforces SSL on connections to your MySQL database and
    // uses a self-signed certificate for MySQL (the latter due to
    // MySQL's poor security record). If you remove them, your app will
    // fail to connect to MySQL with an Access Denied error.
    $aptibleConnection['driver'] = 'mysql';
    $aptibleConnection['collation'] = 'utf8_unicode_ci';
    $aptibleConnection['options'] = [
      PDO::MYSQL_ATTR_SSL_CIPHER => 'DHE-RSA-AES256-SHA',
      PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
    ];
  } elseif ($scheme === "postgresql") {
    $aptibleConnection['driver'] = 'pgsql';
    $aptibleConnection['schema'] = 'public';
  } else {
    error_log("DB_CONNECTION is aptible and DATABASE_URL is set, but the scheme '$scheme' is invalid!");
    return [];
  }
  return $aptibleConnection;
}

Then, add the following key / value pair in your connections array:

'connections' => [
  'aptible' => generateAptibleConnection(),

  // Some other connections you already have
]

Once again, commit the changes.

Bring it all together

At this point, you’re almost ready to deploy.

All that is left to do is put the pieces together by configuring your App to point it to your Database, then you’ll be ready to push your code to Enclave.

To add the required environment variables, use the aptible config:set command as documented below. Make sure you set or substitute $APP_HANDLE and $DATABASE_URL with their proper values.

aptible config:set --app "$APP_HANDLE" \
  "DB_CONNECTION=aptible" \
  "DATABASE_URL=$DATABASE_URL" \
  "APP_DEBUG=false"

Once you’re done, push your code to Aptible by adding Aptible as a git remote for your app, and then using git push to push your code:

git remote add aptible "$GIT_REMOTE"
git push aptible master

Deploy logs will stream to your terminal. They’ll be useful in case anything goes wrong to understand the cause of the failure.

Add an Endpoint

At this point, your App is running on Enclave. What’s next is expose it on the Internet!

Follow the instructions here to proceed: How do I expose my web app on the Internet?.

Next steps

At this stage, your app should be running on Aptible. If you get an error when accessing your app, then you should check your logs via aptible logs.

That being said, your app is not production ready yet. Here are a few recommended next steps.

Session Storage

First, you shouldn’t store your sessions on the local disk (which is the default in Laravel). Whenever you re-deploy your app on Aptible, we re-start it in a new container, which mean sessions stored on disk will be lost, and your users will be logged out.

To store sessions in the database instead, you need to do things.

First, create a new database migration to create tables for your sessions. Use php artisan session:table to create one, and check the migration in your repository, it’ll run the next time you deploy since you automated database migrations, so deploy now.

Second, instruct Laravel to use your database to store sessions by setting the SESSION_DRIVER environment variable:

aptible config:set --app "$APP_HANDLE" \
        "SESSION_DRIVER=database"

Secret Key

Second, your app will be using the APP_KEY from your .env file, which is presumably your development APP_KEY.

You should generate a new one, and set it via this command:

# Make sure you set or substitute $NEW_APP_KEY here!

aptible config:set --app "$APP_HANDLE" \
        "APP_KEY=$NEW_APP_KEY"