10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Flask + Herokuでアプリを動かす

Last updated at Posted at 2019-12-16

Flaskで作ったアプリを、いざ本番環境にデプロイしようと思ったのだけど。なかなか一筋縄でいかず、結局丸一日向き合うことになった。Railsでやってた時は、heroku createからのgit push heroku masterで瞬間に立ち上がっていたのに。

というわけで、FlaskをHerokuに立ち上げるまでを備忘録的に残していく。

開発環境

今回、デプロイにあたって使用した技術はこちら。

  • Python 3.7.5
  • Flask 1.1.1
  • SQL Alchemy
  • Flask Migrate

Flaskチュートリアルだと、db.create_all()コマンドでDBを作成している。しかし、いわゆるマイグレーションファイルに慣れている人からすると、やはりテーブルの状態管理をしておきたいもの。そういう場合には、Flask Migrateを使う。

アプリの初期構築

まずは、アプリの初期構築をやっていく。
Flaskはかなりカスタマイズ度が高いため、開発者によってディレクトリ構成が異なる。まだ、ベストプラクティスは模索中なのだが、最終的にはこんな感じになった。

app/
├── manage.py
├── main
│   ├── __init__.py
│   ├── views.py
│   ├── config.py
│   ├── models.py
│   ├── app.db
│   ├── static/
│   ├── templates/
│   └── instance
│       └──application.cfg
├── Procfile
├── requirements.txt
├── migrations/
└── venv/

プロジェクトの作成

$ cd APP
$ mkdir -p main/{static,templates,instance}
$ cd main
$ touch manage.py requirements.txt Procfile
$ touch main/{__init__,views,models,config}.py

お好みでスタイルシートや、ビュー部分を足す。今回は、HerokuでDBがちゃんと動いて、「Hello world!」を出すまでをやるので、バックエンドのみ。

manage.py

flaskを起動して実行するためのファイル。

manage.py
from main import app
app.run()

main/init.py

flaskアプリを生成。

main/__init__.py
from flask import Flask

app = Flask(__name__)

import main.views

main/views.py

Hello world!を表示するビュー部分。

main/views.py
from flask import render_template
from main import app, db

@app.route('/')
def home():
    return render_template('home/index.html')

設定ファイルの作成

このあたりはベストプラクティスの記事がたくさん上がっているので、そちらを参考にしてみると分かりやすいかと。ここでは、一応動くと、秘密なものは隠せるレベルのものを紹介する。

main/config.py

main/config.py
import os

class BaseConfig(object):
    SQLALCHEMY_TRACK_MODIFICATIONS = False  

class DevelopmentConfig(BaseConfig):
    DEBUG = True
    TESTING = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:///app.db'

class ProductionConfig(BaseConfig):
    DEBUG = True
    TESTING = True
    SQLALCHEMY_DATABASE_URI=os.environ.get('DATABASE_URL')

config = {
    "default": "main.config.BaseConfig",
    "development": "main.config.DevelopmentConfig",
    "production": "main.config.ProductionConfig",
}

def configure_app(app):
    config_name= os.getenv('FLASK_ENV')
    app.config.from_object(config[config_name])
    app.config.from_pyfile('application.cfg', silent=True)

FLASK_ENVは、export FLASK_ENV=developmentなりで設定しておく。ここで言ってるのは、基本BaseConfigの内容を共通で使いつつも、環境(development/production)によって、それぞれ変数の内容を分けているということ。

os.environ.get('DATABASE_URL')はHerkouでDATABASE_UELを自動でデータベースに引っ張ってくれるため本番はこれで設定しておく。

main/instance/application.cfg

instance/application.cfg
SECRET_KEY='XXXXXXXXXXXXXXXXXXX'

ここでは、公にできないAPIキーを載せる。また、必ず.gitignoreに記載して公開しないようにしておく。

設定ファイルを読み込む

用意した設定ファイルを__init__.pyで使えるようにしておく。

main/__init__.py
# 下記の内容を追記する
from main.config import configure_app

app = Flask(__name__, instance_relative_config=True)
configure_app(app)

Herokuにデプロイ

gunicornとpsycpg2のインストール

Herokuにデプロイ、PostgreSQLを使用するために2つのライブラリをインストールしておく。

$ pip install gunicorm
$ pip install psycopg2

Procfileに追記

herokuでアプリを動かすためのコマンドを書き足す。

web: gunicorn main:app --log-file -

インストールパッケージを用意

pip freezeは便利なコマンドで仮想環境中に使ってるライブラリ情報を全部記してくれる。

$ pip freeze > requirements.txt

Herokuアプリにデプロイ

herokuの設定は割愛する。

$ heroku create flask-app
$ git push heroku master
$ heroku config:set FLASK_APP=main
$ heroku config:set FLASK_ENV=production

ここまでで、$ heroku openすれば「Hello world!」が表示されているはず。

データベースの設定

モデルの作成

今回は、テストとしてUserモデルを用意する。

main/models.py
from main import db

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    email = db.Column(db.String, unique=True)

    def __repr__(self):
        return '<User %r>' % self.name

Flask Migrate、SQL Alchemyのインストール

DBをマイグレートするために必要なライブラリをそれぞれインストールしていく。

$ pip install flask_migrate
$ pip install flask_sqlalchemy

モデルの読み込み

設定したモデルを読み込むための準備を__init__.pyに書き足していく。

main/__init__.py
# 下記を追記していく
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

db = SQLAlchemy(app)
migrate = Migrate(app, db)
db.init_app(app)

import main.models

マイグレーション

Flask Migrateコマンドの順に沿ってマイグレーションしていく。

$ flask db init
$ flask db migrate
$ flask db upgrade

これを実行すると、migrationsファイルと、app.dbというデータベースが生成される。

Herokuでマイグレーション

インストールパッケージを用意

先ほどと同じように、新しくインストールしたライブラリをHerokuで使えるように設定していく。

$ pip freeze > requirements.txt

マイグレーション実行

ここが少しハマったのだが、Herokuにはローカルで生成したmigrationsファイルごとサーバーにあげて、db initdb migrateは実行しない。

$ heroku run flask db upgrade

参考文献

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?