How to deploy a Laravel web app on Google App Engine
Tags: laravel, tutorial, devops, webdev
Published: 2019-08-02 09:04:48

*Our developers have been through a lot. These are their stories. This one is told by Indra, one of our senior app-crafters.*

*Indra: I am an experienced software engineer and team lead. I know my projects inside out — I have to. I’m the one making sure all the pieces fit together, the servers are up and running and the hardest tasks get done. When I’m not doing this, I teach and do research at the university. I’m eager to upgrade my skills all the time and pass on to others what I know.*

This week we had a client who wanted his Laravel web app deployed on Google App Engine. There were multiple reasons for this:

- cost (reported to be [cheaper than Amazon](https://blogs.flexera.com/cloud/cloud-cost-analysis/aws-vs-azure-vs-google-cloud-pricing-compute-instances/))
- multi region
- auto scaling

Plus, we already use a lot of Google APIs in this particular app, so it looked like a pretty easy job to do.

What do you know? It wasn’t easy. But I made it work in the end.

Going through this experience, I found the hard way that there’s barely any information on this topic. And the only tutorial I was able to find was posted on the Google community and it was missing a lot of details.

##Before starting:

I recommend before starting your journey of deploying a Laravel app with Google App Engine to read this entire post. Get everything ready. And only then do the deploy. Otherwise you might end up losing a lot of time and stressing yourself out, just like I did.

##Disclaimer:

While I didn’t do any modifications to the nginx setup I will talk about it in a future tutorial. I’m considering doing a tutorial about adding a custom domain and the issues I encountered. But there are already some very good tutorials on YouTube on this topic.

Also, I used standard MySQL for this tutorial, but using big data is possible as well.

Because I didn’t want to make this post hard to read, I added in some sections links to YouTube videos instead of images.

Some of the documentation on Google regarding PHP deployments is lacking, so I substituted it in some places with the documentation from Python. If you plan on deploying a Laravel app with Google App Engine just by following the Google documentation I highly recommend having a look at both.


##Prerequisite reading (you can skip to Preparing for the deploy)

1.) [Google cloud shell](https://cloud.google.com/shell/docs/quickstart)
2.) [PHP on Google Cloud Platform](https://cloud.google.com/php/docs/). We’ll be using Flexible environment so read about that as well.
3.) (Optional) [Documentation for Python](https://cloud.google.com/python/docs/)



##Preparing for deploy

1.) Create a Google Cloud account: [here](https://cloud.google.com/) or more directly [here](https://console.cloud.google.com/getting-started?pli=1). At the moment, you get a 365 day or a $300 credit free trial (whichever comes first). Unless you are a very old user (beta tester) you will also be required to add your credit card, but you will not be charged.

2.) Create a new project (quick video [here](https://www.youtube.com/watch?v=7n9DkOzjwlA&feature=youtu.be&t=35s) if needed)

3.) Create an app engine instance (quick video [here](https://www.youtube.com/watch?v=GZfV2O0orVo) if needed)

4.) We will use [Google Cloud Shell](https://cloud.google.com/shell/docs/quickstart) to deploy. To be able to use it you need to [download the Cloud SDK](https://cloud.google.com/sdk/) for your operating system. For some of the settings, you can use the cloud shell directly from your browser, as seen [here](https://www.youtube.com/watch?v=elnKjoUgSJE&feature=youtu.be). I do not use it, but you can read the docs to find out how. But you should really install it for ease of use. If you run Windows you need to open the installer with administrator rights. Follow the quickstart tutorial from Google for other OSs.

5.) Before you continue with Google Cloud Shell, I recommend [reading this](https://cloud.google.com/php/docs/) about the PHP environment.

6.) Login in the console using command **gcloud auth login**. You will be logged in through the browser. If you want to see all the available commands write **gloud help** in the command line and press **enter**.

7.) Write **gcloud config set project project_id** in the command line, where **project_ id** is the project id you just gave to your newly created project. It can be found on Google console on the first page after you select the project under Project info widget.

8.) To see a list of all your projects type **gcloud projects list**.
This is it for the prerequisites. We will go through the database setup and downloads needed as we move along.

This is it for the prerequisites. We will go through the database setup and downloads needed as we move along. 



##Preparing your project

For this part I used [this tutorial](https://cloud.google.com/community/tutorials/run-laravel-on-appengine-flexible?hl=zh-TW) as an inspiration. You can read it or skip it completely since I will be covering all the steps needed for deploy, except for the file storage part. For that I will give you some info, but not a full blown tutorial.

For this tutorial I will be using as an example an application I am building right now. A simple blog having [Backpack for Laravel](https://backpackforlaravel.com?ref=updivision) as the admin panel. While we’re here, I have to let you know that Vue.js is compatible with Google App Engine. You just need to run **npm install** and **npm run prod** and that will do the trick. In this tutorial we will not be using Vue.js.

1.) Change the directory to your application folder. For ease of use you can set things up like below. You will need to create an **app.yaml** file. Just create it manually at the same level as composer.json. 

![scr1](https://thepracticaldev.s3.amazonaws.com/i/je1f2z2hmerk3k9teg07.jpg)

2.) Now that we have the file we need to setup the database and project details.
 
3.) To set up the project details we will not be using the .env file from Laravel, but instead this app.yaml. Please follow the comments added in my sample of app.yaml to understand how I wrote it. It needs to look like this:

![scr2](https://thepracticaldev.s3.amazonaws.com/i/w3m8zw9sz7ageq5zg6u5.jpg)
![scr3](https://thepracticaldev.s3.amazonaws.com/i/02efq9dr8kyarghf9l3j.jpg) 

4.) Generate the app key. To generate the app key for the Laravel installation we need to run: **php artisan key:generate --show**. And then copy and paste that in app.yaml.

5.) Update composer.json to match Google App Engine requirements. In scripts, add script as below. In **post-install-cmd** script there is a recommendation to add **php artisan cache:clear**, however, from my experience with Google deploy, this does not work. That’s why I recommend leaving it out. I only added the minimum Laravel packages in this composer.json example.
 
![scr4](https://thepracticaldev.s3.amazonaws.com/i/0fiahtjeq0j3p4puz1mv.jpg)
![scr5](https://thepracticaldev.s3.amazonaws.com/i/ox1nz8kgrmyicmssypgh.jpg)

6.) Run **gcloud app deploy** in the google sdk command line (you have to be in the application folder) and when prompted answer **Y**.
 
![scr6](https://thepracticaldev.s3.amazonaws.com/i/fhzwgktimd689sg7gv53.jpg)

7.) Run **gcloud app browse** to see your app.
 
![scr7](https://thepracticaldev.s3.amazonaws.com/i/l9hpfkd0fu5182lw52bo.jpg)


##Setting up cron jobs

Here is the [Google tutorial](https://cloud.google.com/appengine/docs/standard/php/config/cron) for setting up cron jobs. I also took a look at the [Python version](https://cloud.google.com/appengine/docs/standard/python/config/cron). Knowing how to setup the cron jobs with Google App Engine when having a Laravel app is basic. 

Our app had a lot of schedules running and I had a hard time making them work or finding an answer anywhere on the web. Fortunately, we had the same issue with Amazon and already knew a fix. I tried it with Google App Engine and Hallelujah!

1.) Create a cron.yaml file and add this code:

![scr8](https://thepracticaldev.s3.amazonaws.com/i/lc049qtd1cuwx5gnuekl.jpg)
 
2.) In your routes you need to add the scheduler route like this (outside of any middleware):

![scr9](https://thepracticaldev.s3.amazonaws.com/i/04qrci5sv0tc53cdurh0.jpg)
 
3.) Run **gcloud app deploy cron.yaml**.

4.) You can see your crons or run them manually in App Engine Task queues.
 
 
##Setting up an SQL database

This seems to make some people`s head spin, so I’m going to try to make it as easy and visual as possible. I also added a quick video [here](https://www.youtube.com/watch?v=jwtHsT4EmzA&feature=youtu.be).

1.) Go to your Google Cloud console.

2.) In the menu look for SQL and click on it.

3.) Click create instance and choose MySQL.

4.) Choose second generation and choose an id and a password.

5.) Your instance is spinning up.

![scr10](https://thepracticaldev.s3.amazonaws.com/i/yql4pqel63iylsc999yn.jpg)

6.) Now copy the instance connection name and paste it in your app.yaml in **beta_setting cloud_sql_instances: instance_connection_name**.

![scr11](https://thepracticaldev.s3.amazonaws.com/i/9ux843nu6jun5gp6ehax.jpg)
 
7.) Also complete the database connection data in app.yaml. Copy the instance id and paste it for DB_DATABASE. Then copy the instance connection name and add it after /cloudsql/ for DB_SOCKET.
 
![scr12](https://thepracticaldev.s3.amazonaws.com/i/u5qmgn097kx48id5g3ts.jpg)

8.) Deploy the app again.

9.) The database is now empty and I get this error: 

![scr13](https://thepracticaldev.s3.amazonaws.com/i/460vzh604d2jbjbtrozv.jpg)

10.) Connecting to the database:
- Using certificates (read about this in view data section of the article).
- Using command line (read about this in running migrations section of the article).

##Importing a fully migrated database with data in it

To import a full database in your newly created database you need to use Google Bucket.

1.) Dump your current database: **mysqldump -user -p your_database > your_database_dump.sql**

2.) Go to your dashboard and in the left side menu click on Storage. Choose a bucket and upload your database dump.

3.) Go to your google console dashboard and click on you instance id:

 ![scr14](https://thepracticaldev.s3.amazonaws.com/i/nn5sxetmvywq0ibgy93p.jpg)

4.) Click on Import.

![import](https://thepracticaldev.s3.amazonaws.com/i/3axlwa3z549zqv5jm27w.jpg)

5.) Choose the file you uploaded at step 2.

6.) Click on Advanced Options and under database select the name of the database.

7.) Click Import.


##View data

The recommended way to view data, at least in my experience, is to use Workbench and the certificates Google provides. For this part I used [this document](https://cloud.google.com/sql/docs/mysql/external-connection-methods) as inspiration.

1.) Go to your Google Console Dashboard and click on your instance id.

2.) At the top of the screen (right above the charts) choose SSL.

3.) Scroll down and click on Create a client certificate and store them on your computer. I recommend one per computer, but it’s up to you.

4.)  Open MySQL Workbench and in the Connection tab fill in the details from the Overview tab => Connect to this instance a square (for the IP mostly). Use the same user and password as your app.yaml.
 
![scr16](https://thepracticaldev.s3.amazonaws.com/i/t6oq2dueu9fg28enyeoo.jpg)

And in the SSL tab add the certificates you just downloaded. In Use SSL dropdown choose Require. Now you have access to your database.

The next and last step of this tutorial is running migrations and seeders, but feel free to skip it if you got everything you needed already.

![scr17](https://thepracticaldev.s3.amazonaws.com/i/94e9g0dl43jf5joyfjkw.jpg)


##Running migrations and seeders

To run the migrations and seeders you need to do kind of a hack, but if you found another way please let me know in the comments below, because I’ve been looking for a more elegant method.
 
1.) Go and download the [proxy file](https://cloud.google.com/sql/docs/mysql/sql-proxy).

2.) In the Google Cloud Console change directory to the directory where you downloaded the file.

3.) Create a [service account file](https://cloud.google.com/sql/docs/mysql/sql-proxy#create-service-account).

4.) Run this command: 
  
![scr18](https://thepracticaldev.s3.amazonaws.com/i/pyo26tfqcl90rohvhsqj.jpg)

5.) In your .env file put your database and password from Google and use localhost as host.

6.) In command line run any migration or seeder command as you would normally do: **php artisan migrate --seed**

Or you can run a single seeder: **php artisan migrate db:seed --class=SeederClass**

##Setting up storage

To set up storage do this in the **config/filesystem.php** and add a disk for Google:

![scr19](https://thepracticaldev.s3.amazonaws.com/i/88mqh9u5motn0k2a8tc9.jpg)


##Other useful materials on deploying a Laravel app on Google App Engine:

- [Preview and deploy an App Engine application](https://cloud.google.com/shell/docs/quickstart?authuser=1#preview_and_deploy_an_app_engine_application)
- [A Google Cloud Storage filesystem for Laravel](https://github.com/Superbalist/laravel-google-cloud-storage)


I hope you’ve enjoyed this post and found it helpful. Do you have any hints or tips of your own? Or maybe some questions? Feel free to get in touch. Happy coding!