最近、研究室内専用の就活プラットフォームがあればなと思い、とあるサイトを作成しました。
Djangoを用いて開発し、AWSのEC2にデプロイしたんですが、その方法を書いていきます。
誤記等ありましたら、お気軽に言っていただけますと幸いです!
構想
前提
2つあります。
- github上にデプロイしたいWebアプリがあること
- AWS用語の基礎知識があること
(下記が分かっていればOK)- Amazon VPC
- AZ
- サブネット
- ルートテーブル
- インターネットゲートウェイ
- セキュリティグループ
↓説明を載せておくので、参考にしてください!
用語 | 説明 |
---|---|
Amazon VPC | Amazon Virtual Private Cloud(Amazon VPC)とよびます。AWS上に構築するプライベートネットワーク空間のことです。AWS内で複数作成でき、用途ごとに接続先を設定することが可能です。 |
アベイラビリティゾーン(AZ) | AWSが世界各地に配置しているリージョン内にある、1つ以上のデータセンターで構築された小さな区分けのことです。AZ間は低遅延専用線で接続されています。 |
サブネット | ネットワークを分割して作った小さなネットワークのことです。一般的なサブネットの意味と変わりません。AWSの場合、VPC内にサブネットを構成して利用するのが基本です。 |
ルートテーブル | サブネット毎の通信設定ルールです。設定を行うことで、システム内の通信経路を制御し、安全性を確保することができます。 |
インターネットゲートウェイ | VPCとインターネット間の通信を可能にするゲートウェイです。 |
IAMロール | AWSで提供されているサービスの中で、ユーザが実際に操作できる対象(Amazon EC2であればEC2インスタンス)などに操作権限(IAMポリシー)を付与する仕組みのことです。 |
セキュリティグループ | インスタンス単位で通信の許可/禁止を設定できるファイアウォールです。そのため、ルートテーブルより細かな通信制御が可能です。 |
環境
- Windows
- Python 3.12.3
- Django 5.1
- SQLite3 3.45.1
- nginx 1.24.0
- gunicorn 23.0.0
大まかな手順
- EC2を作成して、SSH接続を行う
- 仮想環境に入り、デプロイしたいプログラムをgit clone
- settings.pyのALLOWED_HOSTSにパブリックIPを記述
- migrateできるか確認
- セキュリティグループのインバウンドルールを編集し、ポート8000番のルールを追加
-
python3 manage.py runserver 0.0.0.0:8000
を実行 -
http:Elastic IP:8000
で正常表示されるか確認- ここまででデプロイだけは完了
- nginxおよびgnicornの設定
- アクセス確認
1.AWS EC2インスタンスの作成および設定
では、AWSコンソールにアクセスし、EC2インスタンスを作成します。
設定内容
- インスタンスの種類: t2.micro(無料利用枠に該当)
- AMI(Amazon Machine Image): Ubuntu 20.04 LTS
- ストレージ: デフォルトの8GBで十分です。
- セキュリティグループ: HTTP(ポート80)とSSH(ポート22)を許可するルールを設定
作成が完了したら、EC2インスタンスにSSHで接続します。
作成したEC2インスタンスを選択後、下記画像の「接続」というボタンを押してください。
そしたら、下記のようなメニューが出てくると思います。
「SSHクライアント」を押してください。(画像では既に押しています)
そしたら、下部に「例:」というものがあるはずです。それを下記のように実行してください。
$ chmod 400 鍵の名前
$ ssh -i "鍵の名前" ubuntu@ec2-52-199-26-236.ap-northeast-1.compute.amazonaws.com
Are you sure you want to continue connecting (yes/no/[fingerprint])?
ときかれたら、yes
と入力してください。
これで、EC2の中に入れました。
2.EC2上でDjangoアプリをセットアップ
EC2に接続したら、まずシステムのアップデートを行います。
$ sudo apt-get update
$ sudo apt-get upgrade
次に、必要なパッケージをインストールします。
$ sudo apt-get install python3-pip python3-dev nginx
3.仮想環境に入る
ここからは仮想環境で少し作業をします。
$ python3 -m venv myenv
$ source myenv/bin/activate
なお、仮想環境を出るときは下記コマンドで出れます。
$ deactivate
4.GitHubからコードをクローンし、環境を整える
2021年8月からGithubではセキュリティー強化のために、httpsで認証する場合はトークンベースの認証となりました。
アクセストークンの取得方法は下記記事を参考にしてください。
https://qiita.com/LaP1s/items/69409c6bf08f8c7bca48
$ git clone https://github.com/あなたのgithub垢アカウント名/リポジトリ名.git
$ cd リポジトリ名
$ pip3 install -r requirements.txt
5.settings.pyのALLOWED_HOSTSにパブリックIPを記述
settings.pyがあるディレクトリに入り、下記コマンドで編集します。
$ vim settings.py
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')
ここである疑問が生まれるかもしれません。
「開発サーバーの時はALLOWED_HOSTSを指定しなくても動いたのになぜ指定するのか?」
なぜALLOWED_HOSTSの設定が必要なのか
結論から言うと、
開発環境では、DEBUGがTrueに設定されていたからです。
DjangoはALLOWED_HOSTSが空であっても、DEBUGがTrueになっている場合、localhostや127.0.0.1からのリクエストを許可します。
このため、開発サーバーをローカルで使用する場合、特にALLOWED_HOSTSを指定する必要がなかったんです。
(補足として開発中でも、ローカルホスト以外のIPアドレスやドメインでアクセスする場合は、ALLOWED_HOSTSに追加する必要があります。)
しかし、本番環境ではDEBUGをFalseに設定します。この場合、ALLOWED_HOSTSが空であると、すべてのリクエストが拒否されてしまいます。
DEBUGは詳細なデバック情報を表示します。そのため本番環境でTrueにしてしまうと、悪意のあるユーザーにアプリケーションの内部情報を漏らす危険性があるため、Falseにします。
6.migrateできるか確認
manage.pyのある階層に移動し、migrateを実行する。
$ python3 manage.py migrate
実行できたら大丈夫です!
7.開発サーバーでの確認
開発サーバーはポート8000番を使用するので、EC2インスタンスのセキュリティグループのインバウンドルールを編集します。
下記コマンドを実行し、「http://パブリックIPアドレス:8000」でアクセスしてください。
$ python3 manage.py runserver 0.0.0.0:8000
無事、所望の画面が出れば成功です!
8.gnicornの設定
仮想環境から抜けて作業します。
$ deactivate
GunicornはWSGIサーバーとして、Djangoアプリを処理します。まず、サービスファイルを作成します。
下記のコマンドを打ってgunicornの設定を行っていきましょう。
$ sudo vim /etc/systemd/system/gunicorn.service
以下のように記述します。
日本語の部分は適宜ご自身の環境の合わせて記述してください。
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/リポジトリの名前
ExecStart=/home/ubuntu/仮想環境の名前/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/ubuntu/リポジトリの名前と同じ/Djangoのプロジェクト名.sock Djangoのプロジェクト名.wsgi:application
[Install]
WantedBy=multi-user.target
Gunicornを起動し、自動起動するように設定します。
$ sudo systemctl start gunicorn
$ sudo systemctl enable gunicorn
9.Nginxの設定
Nginxをリバースプロキシとして設定します。設定ファイルを作成します。
$ sudo vim /etc/nginx/sites-available/myproject
以下のように記述します。
日本語の部分は適宜ご自身の環境の合わせて記述してください。
server {
listen 80;
server_name パブリックIP;
location = /favicon.ico {access_log off; log_not_found off;}
location /static/ {
root /home/ubuntu/リポジトリの名前と同じ;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/リポジトリの名前と同じ/プロジェクト名.sock;
}
}
シンボリックリンクを作成してNginxを再起動します。
$ sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
$ sudo systemctl restart nginx
10.セキュリティグループ設定
HTTPのインバウンドルールを追加します。
具体的には、下記の画像を参考にしてください。
そのあとgunicornを再起動します。
$ sudo systemctl restart gunicorn
11.デプロイの確認とトラブルシューティング
NginxとGunicornが正しく動作しているか確認するため、ブラウザでhttp://パブリックIP
にアクセスします。アプリが表示されればデプロイ成功です。
もし動作しない場合、以下2点を確認してください。
- Nginxのエラーログ:
/var/log/nginx/error.log
- Gunicornのエラーログ: サービスファイルで設定した
--access-logfile -
の出力先
12.ソケット通信がうまくいかない…
もしソケット通信がうまく動作しない場合、Gunicornをソケットではなく、ポート8000でバインドし、Nginxがそのポートにリクエストをプロキシする設定に切り替えることができます。
Gunicornをポート8000でバインドする
まず、/etc/systemd/system/gunicorn.service
の設定を修正します。
以下のようにExecStart
の行を修正します:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/yourrepository
ExecStart=/usr/local/bin/gunicorn --access-logfile - --workers 3 --bind 0.0.0.0:8000 myproject.wsgi:application
[Install]
WantedBy=multi-user.target
この設定により、Gunicornが直接ポート8000でリクエストを受け付けるようになります。
Nginxの設定を修正する
次に、Nginxの設定を修正し、プロキシ先をソケットファイルからポート8000に変更します。
$ sudo vim /etc/nginx/sites-available/myproject
以下のようにlocation /
セクションを修正します:
server {
listen 80;
server_name your-ec2-public-ip;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/ubuntu/yourrepository;
}
location / {
include proxy_params;
proxy_pass http://127.0.0.1:8000;
}
}
NginxとGunicornの再起動
設定変更後、NginxとGunicornを再起動して、新しい設定を反映させます。
$ sudo systemctl restart gunicorn
$ sudo systemctl restart nginx
動作確認
再度、ブラウザでhttp://パブリックIP/
にアクセスし、アプリが正しく表示されるか確認します。
この方法では、ソケット通信の問題を回避し、Gunicornがポート8000で直接リクエストを受け取るため、トラブルシューティングに役立ちます。
お金を無駄にしないために
下記3点は使い終わったら必ずやっておきましょう!
- EC2インスタンスを「終了」させる
- セキュリティグループの削除
- Elastic IPの解放
まとめ
以上で今回の解説を終わります!
長い記事を最後まで読んでいただきありがとうございました!
訂正箇所などあれば、お気軽にお声がけいただけますと幸いです。よろしくお願いいたします。