Skip to content
This repository was archived by the owner on Nov 25, 2017. It is now read-only.

Deploying to Heroku

Mattias Levin edited this page Mar 30, 2017 · 5 revisions

This Wiki will explain step-by-step how to deploy the cloud service Heroku.

Application Secret

Play must be configure with a secret key that is used to sign sessions. If not configured the app will not start in production mode https://www.playframework.com/documentation/2.5.x/ApplicationSecret

  • In general this secret should be not put in the source code (anyone can see it)
  • Provide is as an external environment variable or configuration when starting the backend (will not part of the source code)

We will put it in the source to make it easier for us

  1. Open your application.config
  2. Locate play.crypto.secret="changeme"
  3. Replace changeme with a random string e.g. "AB234SAFJD873SDW"
  4. Commit and push your code to Github

Heroku

Create an account

https://dashboard.heroku.com

Login

You will come to the dashboard

Step-by-step instructions

From the dashboard select "Scala Get Started" (works the same for Java) https://devcenter.heroku.com/articles/getting-started-with-scala#introduction

  1. Download and install Heroku CLI on your computer
  2. Open Terminal
  3. Navigate to the root folder of your backend project (where you run your Git commands)
  4. Login from the terminal - heroku login use the same username and password as when creating the account on the web
  5. Create a new backend on the cloud - heroku create
  6. Note down the url (this is where you can reach your app on internet)
  7. Run git remote. 
Will show two remotes (origin and heroku)
  8. Make sure your project compiles before pushing it activator compile
  9. Push to Heroku to deploy you code - git push heroku master
  10. Heroku will download all dependencies, build the backend from the source and start the app automatically. It will take a little while to download all the dependencies the first time (5-15 minutes)
  11. heroku logs - Check that your backend was started without issues - you might run into issues with your DB (see below for solution)
  12. heroku open will launch a web browser pointing to your backend (not useful in our case since it is a Rest service)
  13. Create a file with name Procfile in your root project folder to define how Heroku should start your backend (if file is provided it will be started as a web service by default, you do not need to provide a file)
  14. heroku logs --tail will continuously print the latest files
  15. Use Postman to send a request to one of your REST apis. Remember to use the new URL, e.g. https://glacial-island-95041.herokuapp.com/hello/mattias
  16. Look in the logs

Run Heroku locally on your computer

  1. Create a Procfile in your root project folder
    
web: target/universal/stage/bin/<<YOUR_APP_NAME>> -Dhttp.port=${PORT}
    Replace <<YOUR_APP_NAME>> with your actual application name (found in build.sbt name parameter)
  2. activator compile stage will package your code making it ready for running
  3. heroku local will start your application locally
  4. Use Postman to send a request to one of your REST apis 
http://localhost:5000/hello/mattias

Good way to test before deploying. Same command as Heroku will run when after your pushed the source.

Deploying new changes

  1. Change the source code (add a log statement to your one of your controllers)
  2. Add and commit your changes 
git commit -am "Added log statement"
  3. Push your changes to Github 
git push origin master
  4. Push your changes to Heroku 
git push heroku master
  5. heroku logs --tail to check logs
  6. Use Postman to send a request to one of your REST apis
  7. Your should see the new log

Configure data base

All Heroku apps comes with a free Postgres database. You can modify your code to work with Postgres or install a MySQL DB as a plugin (there is a free version)

All Heroku apps comes with a free Postgress database. You can modify your code to work with Postgress or install a MySQL DB as a plugin (there is a free version)

  1. Go to Heroku web page
  2. Select Elements -> Addons
  3. Filter on Data Stores (left side)
  4. You will find "JawsDB MySQL", spend a few minutes reading
  5. You must add a credit card to your Heroku account before your can use any addons (even if they are free)
  6. Go the Terminal and the root of your app
  7. Install MySQL heroku addons:create jawsdb
  8. heroku addons:docs jawsdb will open the documentation in a web page
  9. heroku addons shows all installed addons
  10. When the database addon was created it also created an environment variable (JAWSDB_URL) with the MySQL Connection String
  11. heroku config:get JAWSDB_URL (you will need to add this string to your Play application configuration)
  12. heroku addons:open jawsdb will open the dashboard (host, username, password etc)
  13. Open your SQL client - SequelPro or SQLWorkBench
  14. Connect to your database using the credentials in step 12
  15. You will already have a database with a strange name, select it
  16. Create you table and columns (same as before)
  17. Update your application.config file with the new credentials (default.url, default.username, default.password)
  18. The default.url is everything after the "@" sign in the connection string (look in the Sample App)
  19. Start your application locally activator run
  20. Make a request from Postman, look in the logs, make sure your app is connecting the new DB
  21. Make a request that creates an entity in the DB
  22. Open you SQL client and reload the DB, your should see a new entry

NEVER store your password in the source code. Someone will find it and hack your application. Instead set the password (maybe also the username and host) as and environment variables.

  1. Open build.sbt
  2. Add this magic line PlayKeys.externalizeResources := false
  3. Open your application.config
  4. Change the clear text password to an environment variable name, e.g. default.password=${?SQL_DB_PASSWORD}
  5. Export the same environment variable in your Terminal 
export SQL_DB_PASSWORD=<YOUR PASSWORD>
  6. Stop and start your server, make sure it still works
  7. Before you can deploy your changes to Heroku your need to create the same environment variable on Heroku 
heroku config:set SQL_DB_PASSWORD=<YOUR PASSWORD>
  8. heroku config will show all your config variables
  9. Commit your changes
  10. Push to your origin master
  11. Push to heroku to deploy - git push heroku master
  12. Use Postmaster to test

Storing images

Your image folder will no longer work, you do not have a file system :) We need to find another solution

  • Store in the DB; works but expensive and not great
  • Use some other 3rd party service to host out image, e.g. Amazon S3

Amazon S3

https://aws.amazon.com/s3/

  • Key value store. Stores any values
  • Have Rest API and SDKs in many programming languages
  • Very cost effective $0.023 per GB
    $0.005 per 1,000 requests
    $0.090 per GB Up to 10 TB / month (OUT)
    There is a free tier for the first year (5 GB of Amazon S3 standard storage, 20,000 Get Requests, 2,000 Put Requests, and 15GB of data transfer out each month for one year)

Create Amazon S3 bucket

  1. Create an account on Amazon S3
  2. Add a credit card (you will not be billed if you keep to the free tier)
  3. "My Billing Dashboard" - Set a billing notification that email you if your service start costing money
  4. "My Security credentials" - Create new Access Keys. Copy the access key and secret key, store safely**
  5. "Services" -> "S3"
  6. "Create Bucket"
  7. "Permissions" - change "Everyone" to read access

** Never ever store your Access Key or Secret Key in Github. Some one will steel them and use them and charge your credit card

Update your backend

Tutorials:
https://devcenter.heroku.com/articles/using-amazon-s3-for-file-uploads-with-java-and-play-2
http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/examples-s3-objects.html

Look at my commit on Github for details https://github.com/gnits-map-projects/PlaySampleApp/commit/a9411989ddc80112ad3a3a1015214f6843d3f1f2

  1. Add S3 settings to the application.conf (the actual values will be set from environment variables when you build your project. We should never store the Access Key and Secret Key in the source code)
  2. Add Amazon SDK as dependency to project in build.sbt
  3. Create a new class S3ImageStore
  4. Create you Amazon client in the constructor
  5. Implement method save(file), get(id), delete(id). Use the Amazon client to upload, get and delete the file
  6. Modify your ImageController to use the new S3ImageStore instead
  7. Make sure everything compile activator clean compile

Deploy Locally

  1. Must set the Access Key and Secret Key as environment variables
  2. Open Terminal and run
 export AWS_ACCESS_KEY=<YOUR KEY> and 
export AWS_SECRET_KEY=<YOUR SECRET>
  3. Start your backend activator run
  4. Test that it works from Postman
  5. You can also look at the content of you Bucket at Amazon S3 dashboard

Deploy to Heroku

  1. You must set your Access Key and Secret Key as environment variables on Heroku
 heroku config:set AWS_ACCESS_KEY=<YOUR KEY> AWS_SECRET_KEY=<YOUR SECRET>
  2. Deploy git push heroku master
  3. heroku logs --tail
  4. And test again