-
Notifications
You must be signed in to change notification settings - Fork 1
Deploying to Heroku
This Wiki will explain step-by-step how to deploy the cloud service Heroku.
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
- Open your
application.config
- Locate
play.crypto.secret="changeme"
- Replace
changeme
with a random string e.g. "AB234SAFJD873SDW" - Commit and push your code to Github
You will come to the dashboard
From the dashboard select "Scala Get Started" (works the same for Java) https://devcenter.heroku.com/articles/getting-started-with-scala#introduction
- Download and install Heroku CLI on your computer
- Open Terminal
- Navigate to the root folder of your backend project (where you run your Git commands)
- Login from the terminal -
heroku login
use the same username and password as when creating the account on the web - Create a new backend on the cloud -
heroku create
- Note down the url (this is where you can reach your app on internet)
- Run
git remote
. Will show two remotes (origin and heroku) - Make sure your project compiles before pushing it
activator compile
- Push to Heroku to deploy you code -
git push heroku master
- 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)
-
heroku logs
- Check that your backend was started without issues - you might run into issues with your DB (see below for solution) -
heroku open
will launch a web browser pointing to your backend (not useful in our case since it is a Rest service) - 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) -
heroku logs --tail
will continuously print the latest files - 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
- Look in the logs
- 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 inbuild.sbt
name parameter) -
activator compile stage
will package your code making it ready for running -
heroku local
will start your application locally - 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.
- Change the source code (add a log statement to your one of your controllers)
- Add and commit your changes
git commit -am "Added log statement"
- Push your changes to Github
git push origin master
- Push your changes to Heroku
git push heroku master
-
heroku logs --tail
to check logs - Use Postman to send a request to one of your REST apis
- Your should see the new log
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)
- Go to Heroku web page
- Select Elements -> Addons
- Filter on Data Stores (left side)
- You will find "JawsDB MySQL", spend a few minutes reading
- You must add a credit card to your Heroku account before your can use any addons (even if they are free)
- Go the Terminal and the root of your app
- Install MySQL
heroku addons:create jawsdb
-
heroku addons:docs jawsdb
will open the documentation in a web page -
heroku addons
shows all installed addons - When the database addon was created it also created an environment variable (JAWSDB_URL) with the MySQL Connection String
-
heroku config:get JAWSDB_URL
(you will need to add this string to your Play application configuration) -
heroku addons:open jawsdb
will open the dashboard (host, username, password etc) - Open your SQL client - SequelPro or SQLWorkBench
- Connect to your database using the credentials in step 12
- You will already have a database with a strange name, select it
- Create you table and columns (same as before)
- Update your
application.config
file with the new credentials (default.url
,default.username
,default.password
) - The
default.url
is everything after the "@" sign in the connection string (look in the Sample App) - Start your application locally
activator run
- Make a request from Postman, look in the logs, make sure your app is connecting the new DB
- Make a request that creates an entity in the DB
- 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.
- Open
build.sbt
- Add this magic line
PlayKeys.externalizeResources := false
- Open your
application.config
- Change the clear text password to an environment variable name, e.g.
default.password=${?SQL_DB_PASSWORD}
- Export the same environment variable in your Terminal
export SQL_DB_PASSWORD=<YOUR PASSWORD>
- Stop and start your server, make sure it still works
- 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>
-
heroku config
will show all your config variables - Commit your changes
- Push to your origin master
- Push to heroku to deploy -
git push heroku master
- Use Postmaster to test
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
- 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 an account on Amazon S3
- Add a credit card (you will not be billed if you keep to the free tier)
- "My Billing Dashboard" - Set a billing notification that email you if your service start costing money
- "My Security credentials" - Create new Access Keys. Copy the access key and secret key, store safely**
- "Services" -> "S3"
- "Create Bucket"
- "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
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
- 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) - Add Amazon SDK as dependency to project in
build.sbt
- Create a new class
S3ImageStore
- Create you Amazon client in the constructor
- Implement method
save(file)
,get(id)
,delete(id)
. Use the Amazon client to upload, get and delete the file - Modify your
ImageControlle
r to use the newS3ImageStore
instead - Make sure everything compile
activator clean compile
- Must set the Access Key and Secret Key as environment variables
- Open Terminal and run
export AWS_ACCESS_KEY=<YOUR KEY>
andexport AWS_SECRET_KEY=<YOUR SECRET>
- Start your backend
activator run
- Test that it works from Postman
- You can also look at the content of you Bucket at Amazon S3 dashboard
- 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>
- Deploy
git push heroku master
heroku logs --tail
- And test again