AWS EC2にDjangoアプリのデプロイ① 〜インスタンス作成からマイグレーション動作確認

Django

Djangoで自身の学習用に画像認識アプリを作成してみました。
画像分類モデル作成→学習させたモデルをwebに組み込むという流れを掴むためだけに他の方の記事を参考にしながら付け焼き刃で作ったのでかなり簡素な内容になってますが、これをAWS EC2にデプロイしてみたいと思います。

GitHub-学習コード

GitHub-Djangoコード
今回はインスタンスの作成からLinux上でのマイグレーション、動作確認までを記載しています。

使用環境

・Ubuntu
・Python3
・virtualenv
・Django
・PostgreSQL
・Nginx
・gunicorn

ローカルでの事前準備

git cloneを使ってアプリをサーバー上に設置するため、gitにpushするための事前準備をします。

gitに公開したくないものを環境変数で管理

SECRET_KEYやDATABASE情報など外部に漏れると困るものはdjango-environというパッケージで管理します。

$ pip install django-environ

manage.pyが置いてあるのと同じディレクトリに.envを作成し、以下のように設定します。

SECRET_KEY=c)!)zv)!hnv!w%24jhz(j8zb&^_58hxy%xu%cbi)ph*aaabbbcc
DEBUG=False
DATABASE_URL=sqlite:///db.sqlite3
ALLOWED_HOSTS=[]

settings.pyの一部を書き換えます。

import os
import environ

env = environ.Env()
env.read_env('.env')

BASE_DIR = Path(__file__).resolve().parent.parent

SECRET_KEY = env('SECRET_KEY')

DEBUG = env('DEBUG')

ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')

DATABASES = {
    'default': env.db(),
}

manage.pyと同じディレクトリに.gitignoreを作成しhttps://www.gitignore.io/api/django
の遷移先で表示されたテキストをコピーし.gitignoreに貼り付けます。

requirements.txtを作成

本番環境にインストールする必要があるパッケージリストを記載しているファイルを作成します。これを作成しておくと、本番環境でリストにあるライブラリやソフトを一括でインストールできるので便利です。
manage.pyと同じディレクトリ上で下記をコマンドします。

$ pip freeze > requirements.txt

作成されたファイルを見ると、ソフトが一覧化されていると思います。

※ちなみに、anaconda経由で作成すると、バージョンではなく「@ file:///opt/concourse」といった感じに記載されていることがありますが、このまま本番環境でpip installするとエラーが出る可能性がありますので、@以降を削除し「conda list -e > conda_requirements.txt」で記載されているバージョンを参考に書き換えておきましょう。私はバージョンの書き換えは特にせず@以降を削除しただけでなんとかうまくいきました。上記画像は@以降を削除した後の内容です。

参考サイト
pip freeze > requirements.txtで作成すると @file:ができる?

gitにpushする

ここまで準備をしたらローカルにあるアプリをgit pushします。

インスタンス作成

インスタンス作成

AWSにアクセスし、サービスでEC2を選択しインスタンスを開きます。(既にアカウントを作成している前提で進めます)

インスタンスを起動をクリックします。

少し下にスクロールすると表示されるUbuntuを選択します。無料対象枠が2つありますが、今回は上の方を選択しました。

無料対象枠であるt2.microが選択されている状態で確認と作成をクリックします。
細かな設定は一旦スキップして、起動をクリックします。

ssh接続する際に必要となるキーペアを作成します。新しいキーペアの作成を選択し、任意のキーペア名を入力してキーペアをダウンロードしてから、インスタンスの作成をクリックします。

Elastic IPの設定

インスタンスを作成するとパブリックIPが付与されます。
このパブリックIPで、インターネットを介してインスタンスへ接続することができます。しかし、インスタンスを再起動する度にパブリックIPが変わってしまうため、外部からのアクセスが頻繁にあるようなインスタンスの場合不便なので、事前にIPアドレスの固定化をしてくれるElastic IPの設定をしていきます。

EC2より、Elastic IPを選択し、右上のElastic IPアドレスを割り当てるを選択します。

次に設置はデフォルトのままにして右下の割り当てを選択します。

割り当てられたElastic IPを選択し、アクション→Elastic IPアドレスの関連付けをクリックします。

「インスタンス」には、Elastic IPを付与したいインスタンスを、
「プライベートIPアドレス」にはそのインスタンスのプライベートIPを選択し、右下の関連付けるをクリックします。これでElastic IPの設定は完了です。

ssh接続

次にLinuxインスタンスへsshを使用して接続します。
まず先ほどダウンロードしたキーペアがあるディレクトリまでcdで移動します。

AWSサイトのインスタンスをクリックし、先ほど作成したインスタンスIDがリンクになっているのでそこをクリックします。

画面上部の接続をクリックします。

sshクライアントタブに表示されているコマンド例を参考にコマンドしていきます。

$ chmod 400 キーペア名.pem
$ ssh -i "キーペア名.pem" ubuntu@ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com

接続すると最初以下のメッセージが出てきますので、yesを入力しEnterします。

接続が成功するとこのようになります。

postgreSQL設定

ssh接続したらまずインストール可能なパッケージの一覧を更新します。

 [ubuntu内]$ sudo apt-get update

python3、postgreSQL、nginx関連のパッケージをインストールします。

 [ubuntu内]$ sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx

続いて以下をコマンドします。

[ubuntu内]$ sudo -u postgres psql

「postgres=#」と表示がされるので、database名は任意の名前をつけます。

[postgres=#] CREATE DATABASE mldjangoapp;

今回はmldjangoappとつけました。
「CREATE DATABASE」と表示されるのを確認したら、次はユーザー名とパスワード、その他を設定していきます。適宜内容は変更してください。

[postgres=#] CREATE USER mldjangouser WITH PASSWORD 'p@ssword';
[postgres=#] ALTER ROLE mldjangouser SET client_encoding TO 'utf8';
[postgres=#] ALTER ROLE mldjangouser SET default_transaction_isolation TO 'read committed';
[postgres=#] ALTER ROLE mldjangouser SET timezone TO 'UTC+9';
[postgres=#] GRANT ALL PRIVILEGES ON DATABASE mldjangoapp TO mldjangouser;

¥qでpsqlツールを終了します。

[postgres=#] ps aux

でpostgreSQLが起動しているのを確認します。

GitHubの鍵を登録する

git経由でアプリデータを設置するためにまずgithubの鍵を登録します。

ubuntu内(ubuntu@ip-xx-xx-xx-xx:~$)に入っている状態でgitをインストール。

 [ubuntu内]$ sudo apt-get install git

sshディレクトリに移動します。

[ubuntu内]$ cd ~/.ssh

鍵作成

[ubuntu内:~/.ssh]$ ssh-keygen -t rsa

鍵名はec2_github_keyとします。

Enter file in which to save the key (): ec2_github_key
Enter passphrase (empty for no passphrase): [Enter]
Enter same passphrase again: [Enter]

これでsshディレクトリに鍵が作成されます。
lsコマンドで鍵が作成されているか確認しましょう。

次に以下をコマンドし、configに設定値を明記します。

[ubuntu内:~/.ssh]$ vi ~/.ssh/config

以下をコピペ(内容は適宜変更してください)し:wqで保存します。

Host github
  HostName github.com
  User git
  IdentityFile ~/.ssh/ec2_github_key

ec2_github_key.pubの中身を確認します。

[ubuntu内:~/.ssh]$ cat ~/.ssh/ec2_github_key.pub

出力されたssh-rsaから最後までをコピーしてどこかに記録しておきます。

https://github.com/settings/keysにとんでNew SSH keyをクリックし、タイトルと先ほどコピーしたssh-rsaからのキーを入力してsshkeyを作成します。

登録できているか確認

[ubuntu内:~/.ssh]$ ssh -T github
Hi ユーザー名! You've successfully authenticated, but GitHub does not provide shell access.

次はec2側に鍵を登録します。

[ubuntu内:~/.ssh]$ ssh-add ~/.ssh/ec2_github_key

もし「Could not open a connection to your authentication agent.」のエラーが出たら、

[ubuntu内:~/.ssh]$ eval "$(ssh-agent)"

これをしてから「ssh-add ~/.ssh/ec2_github_key」を再度コマンドします。

Django環境構築

cdでubuntuのトップ階層に戻り以下をコマンドしvirtualenvをインストールします。

[ubuntu内]$ sudo -H pip3 install virtualenv

仮想環境を作成します。今回myenvという名前で作成します。

[ubuntu内]$ virtualenv myenv

作成した仮想環境をアクティベートします。

[ubuntu内]$ source myenv/bin/activate

「(myenv) ubuntu@ip~」となったことを確認します。
仮想環境上でdjango、django動作の安定性や速度向上のために使用するWSGIサーバーのgunicorn、postgreSQLを操作するためのpsycopg2をインストールします。

[(myenv) ubuntu内]$ pip install django gunicorn psycopg2

次にpillowという画像処理ライブラリもインストールしておきます。

[(myenv) ubuntu内]$ pip install pillow

次にgit cloneをしてgit上のアプリケーションフォルダをデプロイします。ml-django-app部分にはデプロイしたいアプリケーション名を入れてください。

[(myenv) ubuntu内]$ git clone git@github.com:xxxxx/ml-django-app.git

cd ml-django-appでアプリ内に移動します。念のためlsなどで全てのファイルがデプロイされているか確認します。
manage.py(アプリトップの階層)があるディレクトリに移動し、あらかじめ作成しておいたrequirements.txtを使ってパッケージリストを一気にインストールします。

[(myenv) ubuntu内:~/ml-django-app]$ pip install -r requirements.txt

本番環境でも環境変数を使用するためenvironをインストールします。

[(myenv) ubuntu内:~/ml-django-app]$ pip install django-environ

manage.py(アプリトップの階層)があるディレクトリにいるか確認し、envファイルを作成します。

[(myenv) ubuntu内:~/ml-django-app]$ vi .env

DATABASE_URLとALLOWED_HOSTSの内容がローカルのenvと異なります。

SECRET_KEY=c)!)zv)!hnv!w%24jhz(j8zb&^_58hxy%xu%cbi)ph*aaabbbcc
DEBUG=False
DATABASE_URL=postgres://mldjangouser:p@ssword@localhost:/mldjangoapp
ALLOWED_HOSTS=54.178.251.205

DATABASE_URLは先ほどpostgreSQLで設定した内容と同じものを入力します。(postgres://ユーザー名:パスワード@localhost:(ポート番号)/データベース名)
ALLOWED_HOSTSはElasticIPを入力します。終わったら:wqで保存します。

マイグレーション、動作確認

マイグレーション

マイグレーションを作成します。

[(myenv) ubuntu内:~/ml-django-app]$ python3 manage.py makemigrations
No changes detected

マイグレーションの実行をします。

[(myenv) ubuntu内:~/ml-django-app]$ python3 manage.py migrate

8000番ポートアクセスの許可

djangoは8000番ポートを使用しているため、8000番ポート通信をEC2コントロールパネルで許可します。
EC2で起動中のインスタンスをクリックし、セキュリティタブをクリックします。

セキュリティグループのリンクをクリックし、インバウンドルールの編集をクリックします。

ルールの追加をクリックし、8000番ポートを設定、ルールを保存をします。

アプリ起動

アプリを起動します。

[(myenv) ubuntu内:~/ml-django-app]$ python3 manage.py runserver 0.0.0.0:8000

問題がなければ以下のようなメッセージが表示されます。

実際にブラウザで「xxx.xxx.xxx.xxx(ElasticIP):8000」にアクセスし、各ページの動作確認をします。
ローカルで開発した時と同じ動作が確認できていれば、一旦ここまでのデプロイ作業は完了です。次はnginxとgunicornを使用してアクセスすると自動的にサーバーとアプリが立ち上がるように設定をしていきます。

コメント