Help us understand the problem. What is going on with this article?

[Python]AWSを使ってec2+RDS環境を構築したい

More than 1 year has passed since last update.

前回の続き↓
[Python]AWS + Tornadoの環境構築
・AWSのEC2とRDSを使ってインフラ構築
・EC2のOSはAmazon Linux
・RDSのDBMSにはMySQL
・サーバ側はPython3
・DBのORMにはsqlalchemy
・マイグレーションにはalembic
・コーディング規約はpycodestyle(pep8)
こんな感じのチャットアプリを作ろうと思います。

参考
Python の Alembic を使って RDB のスキーマを管理する
↓やることはほぼこれです。
Alembicでマイグレーションスクリプトを自動生成する最小限の設定

環境設定

Alembicを使います
モデルを別で書きたかったので、meta_dataを使う形式にしてみます。

pip install alembic
pip freeze | grep alembic
>alembic==0.9.6

migrationの下準備

alembic init migrations #migrationsフォルダが作成される
vi alembic.ini 
alembic.ini
sql_alchemy.url=DBへのパス
#パスの書き方は後述

今回はモデルを別ファイルで定義することにしたので、models.pyをmigrationsディレクトリと同じ階層に作る。

models.py
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    name = Column(String(255), nullable=False)

    def __repr__(self):
        return "<User(name='%s')>" % (self.name)

migrations/env.pyでこのmodelsをインポートする。

env.py
import models
target_metadata = models.Base.metadata
#target_metadata = None

これで下準備は完了なのでmigrationすればいいはず…

alembic revision --autogenerate -m "Add account table"

するとエラー

ERROR [alembic.util.messaging] Target database is not up to date.
  FAILED: Target database is not up to date.

stackflowを見て(ここには書いてないけど)、どうやらalembic.iniのscript_locationが間違ってたみたい。エラーですぎていろいろいじっていたからずれてしまっていた。
一応参考↓
Error when autogenerate migration scripts with alembic

alembic.ini
script_location = migrations #←作ったフォルダ名

これでmigrationしてみる。

alembic revision --autogenerate -m "Init tables"
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'users'

うまくいったみたい。migrations/versions直下にマイグレーションファイルができている。
あとはalembic upgrade headすればよい!

さっそくするとDBのパスが間違っていることが判明。

sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")

のようなエラーが出てきた。
localhost(この場合ec2インスタンス)からDBに繋げないらしい。
mysql -u root -p -h エンドポイント名  なら繋げてるのに…

下のURLを見てみたけれどRDSを使わずにMySQLを使っているので関係なさそう。(一応やった)
EC2にMySQLインストールと設定確認
後から見返したら全く不要な作業だったと思う。

調べてみると、alembic.iniのsqlalchemy.urlが理解できていなかったみたい。
構造は sqlalchemy.url = driver://user:pass@host/dbname

driver: DBMS名+ライブラリ名、何を使ってDBにアクセスするか
user: DBのユーザー名、RDSの設定をしていればインスタンスページに書いてある
pass: RDS設定時に決めたパスワード
host: DBのホスト名、今回はec2内でmysqlを稼働させるのではなく、RDSを使いたいのでRDSのホスト名(つまりエンドポイント)
dbname: 接続するDBの名前、わからなければRDSに直接接続してshow databasesすれば確認できると思う

自分の場合はMySQLを触るためのライブラリを入れていなかったことが判明したのでpymysqlを導入。

#v_env下だとpymysqlがなかったので導入
pip install pymysql

するとURLは以下のようになる。
sqlalchemy.url = mysql + pymysql://root:(password)@example-rds-mysql-server.fmi3ou2hr9.us-east-2.rds.amazonaws.com/exampledb
これでうまくいった。
もう一度やると、env.pyで使っているmodelモジュールがないとのこと。パスが通ってなかったのでenv.pyを修正。

env.py
#target_metadata = Noneとなっているところを以下に修正
### modelsをインポートするためにパスを追加 ###
import os
import sys
root_dir = os.getcwd()
sys.path.insert(0, root_dir)
### metadata を設定 ### 
import models
target_metadata = models.Base.metadata

うまくいくか…

alembic upgrade head
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> e76a42708e85, Init tables

ようやくRDSにテーブルを作ることができた!migrations/versionsにあるmigrationスクリプトも自動生成されててalembicすごい。

まとめ

やったこととしては、
①alembicの導入、pymysqlの導入
②alembic initでフォルダ作成
③alembic.iniでDBのパスとscript_locationを修正
④env.pyでmodelsモジュールをインポート
⑤migrationファイルをautogenerateして、upgrade head
になります。

長くなってしまったので続きは別記事で。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした