How to deploying your API
Today I'm going to walk you through how to deploy your API using either Heroku or AppEngine! They're fairly similar services, but I wanted to give you a chance to use both and see what you prefer. By using two services I can also show you how different platforms expect a different file structure for your apps.
Heroku is a platform as a service that's designed specifically for serving applications. You don't need to have a credit card to create an API on Heroku, but you'll be limited by what's offered through the free tier.
AppEngine is part of Google Cloud and is also a way to serve apps. You do need a credit card to create an app on AppEngine, but once it's set up you can go to your appengine settings and set the daily spending limit to 0. This will keep you from being charged.
I'll start with Heroku, then talk about AppEngine and finally show you how to query your API using Python. :)
Heroku
Edit files on GitHub
For your conviencice, I've created an extrememly simple sample app on GitHub: https://github.com/rctatman/minimal_flask_example_heroku. You'll want to head over to GitHub, fork this repo and then edit the relevant files for your specific app.
Here's a quick guide to each of the files and information that tells you which to edit:
Files you'll put the code you wrote yesterday into
In yesterday's notebook, as the very last exercise we wrote two cells of code, each of which will be a single file.
serve.py: This is the file you should put the code from the first cell in; this is where you'll define the functions that will read in your trained models.
script.py: This is where you'll put the code from your second notebook. This is what will define the behavior of our different endpoints.
Files you'll need to add
If you are going to use a pre-trained model, be sure to add it to your repo so that you can read it in. If you like, you can store your models in a new file, but if you do this be sure to update the file path of the code that you read them with. So if you have a model called "my_model.pkl" in a folder called "models", you'll need to update the code that reads it in from this:
to this:
Files you'll need to edit
README: This is the file you're currently reading. You'll probably want to update this to have information about your specific API and how to use it.
openapi.yaml: You can relace this file with the specification file that we wrote on day one. (The notebook's here if you need a refresher).
requirements.txt: This file has information on what packages you use in your app. You need to make sure that you list every package you import and also gunicorn. If you remove the line with gunicorn or forget to include a package you import somewhere else, you'll get an error when you try to run your app.
runtime.txt: This file tells Heroku which version of Python to use to run your app. You'll only need to update this file if you pickled your model file using a different version of Python & that's causing your code to break.
File you don't need to edit
LICENSE: This file is the license your code is released under. If you don't include a license, other folks won't be able to reuse your code. If you fork this repository for your own work, you'll need to keep the license. I've used Apache 2.0 here because that's the same license as public Kaggle Kernels.
Procfile: This file is required by Heroku. It tells Heroku how to run your application. You probably don't need to change this file.
Deploy to Heroku
Once you've edited your files, you're ready to deploy to Heroku.
Create a new account or sign into your existing account
Create your app
Click on “create new app”
Give it a name & choose your region
Hit “create app”
Connect to GitHub repo
Click on the Deploy tab
CLick on Connect GitHub & search for the repo you want to add (make sure you've forked the repo; you'll only be able to connect to a GitHub repo you own)
Deploy your app
Next to “Manual deploy” hit “Deploy Branch”
If you hit “open app”, you should open a new browser page that points to the URL your app is served from. (Unless you put something at the endpoint "\" it will probably just be a 404 page.)
And that's it! Your app is live. :)
What if you run into trouble? If your app isn't working, click on the [MORE] button in the upper right hand corner, then on "View logs". This will show a detailed log of whatever went wrong.
AppEngine
For your convenience, I've created an extremely simple sample app on GitHub: https://github.com/rctatman/minimal_flask_example_appengine. You'll want to head over to GitHub, fork this repo and then edit the relevant files for your specific app.
Here's a quick guide to each of the files and information that tells you which to edit. Note that this is different from the files for Heroku; the two different services expect different file configurations.
Edit files on GitHub
Files you'll put the code you wrote yesterday into
In yesterday's notebook, as the very last exercise we wrote two cells of code, each of which will be a single file.
serve.py: This is the file you should put the code from the first cell in; this is where you'll define the functions that will read in your trained models.
main.py: This is where you'll put the code from your second notebook. This is what will define the behavior of our different endpoints.
Files you'll need to add
If you are going to use a pre-trained model, be sure to add it to your repo so that you can read it in. If you like, you can store your models in a new file, but if you do this be sure to update the file path of the code that you read them with. So if you have a model called "my_model.pkl" in a folder called "models", you'll need to update the code that reads it in from this:
to this:
Files you'll need to edit
README: This is the file you're currently reading. You'll probably want to update this to have information about your specific API and how to use it.
openapi.yaml: You can relace this file with the specification file that we wrote on day one. (The notebook's here if you need a refresher).
requirements.txt: This file has information on what packages you use in your app. It's currently empty becuase I didn't import any packages, but you'll need to include all the packages you use, one per line as show below. If you forget to include a package you import somewhere else, you'll get an error when you try to run your app.
Files you don't need to edit
LICENSE: This file is the license your code is released under. If you don't include a license, other folks won't be able to reuse your code. If you fork this repository for your own work, you'll need to keep the license. I've used Apache 2.0 here because that's the same license as public Kaggle Kernels.
app.yaml: This file tells AppEngine which version of Python to use to run your app. You don't need to edit this.
index.yaml: This file is required by AppEngine and tells it how to index the data you send to Datastore. Since we're not using Datastore, we can just ignore this file.
Deploy to AppEngine
Now you're ready to deploy your app! We're going to be interacting with AppEngine via Cloud Shell. You can use the GUI as well, but I personally like Cloud Shell. :)
Don't forget to sign into your GCP account or create one if you don't have one! You'll also want to set up a billing account you can connect your project to in order to build your app.
I know this looks like a lot of steps, but I've tried to be very clear so you know what to do at each step.
Copy your repo into your Cloud Shell VM
Either edit and use the button in the GitHub README OR
Go to the Cloud Shell (https://console.cloud.google.com/cloudshell/editor) and clone it yourself: git clone [GITHUB-URL]
Move into the repo by running
cd [NAME-OF-REPO]
in the black console at the bottom of the screen, which is where you'll run all the commands from here on out. (You'll need to replace [NAME-OF-REPO] with your actual repo.)
Launch your app locally (helpful for testing)
Use this command to test deploy your app:
dev_appserver.py ./app.yaml
Once you see output like: "Booting worker with pid" in the command line, you can see your app by hitting the button that looks like <> in a browser window at the top right hand side of your screen. This will open a new tab running your app. If you haven't put anything at the "\" end point, this will just a 404.
Use
CTRL + C
to close your app
Create a project & enable billing.
Run these commands, replacing [YOUR-PROJECT-ID] with your actual product ID.
gcloud projects create [YOUR-PROJECT-ID]
gcloud config set project [YOUR-PROJECT-ID]
You'll see your project id in yellow
Enable cloud build by going to this URL & clicking "enable", then following the prompts: https://console.developers.google.com/apis/library/cloudbuild.googleapis.com.
Launch the app!
Deploy your app by running this command:
gcloud app deploy ./index.yaml ./app.yaml
Pick a region (I'd recommend one closer to you to reduce latency)
Enter "y" when asked whether you want to continue
After it's finished deploying, your app will be at the URL: https://[YOUR-PROJECT-ID].appspot.com/
You can query your app directly from Cloud Shell! :)
Run these commands to query your app, replacing the [text in brackets] as applicable for your project.
python
import requests
requests.[METHOD]('https://[YOUR-PROJECT-ID].appspot.com/[YOUR-ENDPOINT-NAME], json=[JSON-TO-SEND]).json()
In [1]:
Querying APIs using requests
Ok, now that you've got your app up and running, how do you actually query it? Probably the simplest way to do this from Python is using the requests library. The anatomy of a request is like so:
requests.method
This will send a request to your API and, hopefully, return a response. If it works, you'll probably just see the response code output:
<Response [200]>
In order to get the data that was returned, you can append .json()
to parse any JSON that was returned or .text
just to see the raw strings.
Here are some example queries for the sample app I've talked about in my notebooks so far. (Note that I'm only using the free tier of each service to serve these, so if people make a lot of requests and I hit my quota, they'll stop working.)In [2]:
Out[2]:
For the AppEngine version, I called my endpoint "api" instead of "extractpackages" and I'm honestly just too lazy to change it at this point. Otherwise it looks pretty much the same, but with a different URL.In [3]:
Out[3]:
And that's it! Over the last three days we've:
Designed an API and written a specification
Prepared our code & models to be put in a Flask App
Written the app itself
Deployed and used our very own APIs
I hope you found these notebooks helpful and learned something new about APIs. I'd love to hear about what you all built in the comments!
Last updated