LoginSignup
7
6

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-01-12

前回の続き↓
[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
になります。

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

7
6
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
7
6