2020-09-15: Work note for running an API server for machine learning, natural language processing, etc. on heroku.

First, create a minimal server and run it locally.

  • $ python3 -m venv venv
  • $ source venv/bin/activate
  • create “server/init.py” and write minimal server python
from flask import Flask

app = Flask(__name__)

def create_app():
    return app

@app.route('/')
def root():
    return "OK"
- Minimal server implementation
- I had a habit of doing app.run with `if __name__ == "__main__"`, but I don't do that anymore, even in official Flask tutorials.
    - Specify the module to be started in the environment variable, and start it with flask run.
        - [explanation on the heroku side](https://devcenter.heroku.com/articles/flask-memcache) does that too.
        - Setting environment variables may seem tedious, but you can use dotenv
        - The official explanation uses [[Flask Blueprint]], but I decided that's not necessary at the minimum.
    - create_app is used to call from gunicorn later
  • $ python server/__init__.py
    • ModuleNotFoundError: No module named 'flask'
      • $ pip install --upgrade pip
      • $ pip install flask
    • OK
  • $ flask run
    • NG because environment variables are not set
    • Error: Could not locate a Flask application. You did not provide the “FLASK_APP” environment variable, and a “wsgi.py” or “app.py” module was not found in the current directory.

  • create “.env” file
    • $ code .env :
FLASK_APP=server
FLASK_ENV=development

Deploy to heroku

  • $ git init
  • create “.gitignore” :
venv/
.env

*.pyc
__pycache__/
- .env ignore?
    - If you don't IGNORE, you don't need to do $ heroku config:set FLASK_APP=server later
    - This is to avoid the common accident of putting API keys, etc. that should not be made public in .env and pushing them to the public repository.
  • $ git add .

  • $ git commit -m 'minimal Flask server'

  • $ heroku create foo-server

    • This is creating an app from a local console, but if you are already using it from a browser, just follow the instructions in the browser.
      • $ heroku git:remote -a foo-server
  • $ git remote

    • heroku

  • I’m going to push here.

    • $ git push --set-upstream heroku master
    • I can push, but build fails.
  • $ pip install gunicorn

  • $ pip freeze > requirements.txt

  • create “Procfile” :

web: gunicorn server:"create_app()"
- name "server" points the module on "./server"
  • $ heroku config:set FLASK_APP=server
  • add and commit
  • $ git push heroku master
    • Make sure the build is successful
  • $ heroku open
    • Open it in your browser and make sure it says OK.

Implement the required API

  • View the build log when pushing and the error log when accessing
    • $ heroku logs --tail
    • You forgot to include the necessary files, and you get a runtime error when accessing the system.
    • Or error at build time: [mecab no such file or directory: /usr/local/etc/mecabrc https://medium.com/@jiraffestaff/mecabrc-%E3%81%8C%E8%A6%8B%E3 81%A4%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%84%E3%81%86%E3%82%A8%E3%83%A9%E3%83%BC-b3e278e9ed07]
  • By default, a route only answers to GET requests.doc
    • @app.route('/', methods=['GET', 'POST'])
  • JSON
    • property json: Optional[Any] doc: Incoming Request Data
      • The parsed JSON data if mimetype indicates JSON (application/json, see is_json).

  • If you call from other origins: Flask-CORS is required

“No web processes running”

  • I typo’d the file name in the Procfile.
  • The build itself goes through…

----old memo Heroku+Flask 2019-6-07 memo

This page is auto-translated from /nishio/Heroku+Flask using DeepL. If you looks something interesting but the auto-translated English is not good enough to understand it, feel free to let me know at @nishio_en. I’m very happy to spread my thought to non-Japanese readers.