【Django】AWSのEC2にnginx+gunicornでDjangoのアプリをデプロイする方法
前提
- Djangoのアプリは作成済みで、DBはmysqlを使用している。githubで管理していてそこからクローンする。
- EC2はAmazonLinux2を使用する。
EC2でサーバーを立てる
AMIはAmazonLinux2で立てる。
パブリックIPを有効にするのを忘れない。
セキュリティグループのインバウンドは、以下の設定にする。
HTTP 80 0.0.0.0
SSH 22 0.0.0.0
カスタムTCP 8000 0.0.0.0
必要なものをインストールする
EC2で立てたサーバーに接続し、その中で以下のコマンドを打つ。
sudo passwd ec2-user
sudo passwd root
sudo yum update
sudo yum install python3
sudo yum install git
sudo amazon-linux-extras install nginx1
sudo pip3 install django
sudo pip3 install gunicorn
Djangoのアプリの設定を行う
githubからDjangoアプリをクローンする
まずはgithubからクローンしてくるため、SSHキーを作成する。
下記のコマンドを打ち、3回エンターを押せば作成できる。
ssh-keygen
次に、以下のコマンドで公開鍵の方を表示して、それをgithubの設定からSSH keysに行き、公開鍵を張り付けてクローン出来るようにする。
cd ~/.ssh
cat id_rsa.pub
これでクローンの準備は整ったが、その前にローカルで以下のコマンドをたたき、
インストールしたいライブラリをまとめておく。
pip freeze > requirements.txt
githubからDjangoアプリをクローンしてくる。
cd ~
git clone git@github.com:[アカウント名]/[リポジトリ名].git
ライブラリのインストールとコードの修正
必要なライブラリをインストールする
cd リポジトリ名
pip install -r requirements.txt
mysqlclientをinstallしようとするとエラーが出ることがある。
その場合は以下のコマンドを打ってから、mysqlclientをinstallする。
sudo pip3 install mysql-devel
sudo pip3 install --upgrade pip setuptools
sudo yum install python3-devel
sudo yum install gcc
envファイルを使用している場合は作成する。
内容は各々のものを書き込む。DBの設定など。
sudo vi .env
settings.pyのALLOWED_HOSTSにサーバーのパブリックIPを入れる。
また、STATIC_ROOTを追加しておく。
sudo vi settings.py
ALLOWED_HOSTS = [*.*.*.*]
STATIC_ROOT = os.path.join(BASE_DIR,'static')
mysqlの設定
以下のコマンドでmysqlをインストールする
# MySQL yumリポジトリからMySQL8.0のRPMパッケージをダウンロード
sudo yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
# MySQLのGPGキーの有効期限切れの可能性があるため、新しいGPGキーをインポートする
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
# MySQLのインストール
sudo yum install --enablerepo=mysql80-community mysql-community-server -y
# MySQLバージョン確認
mysql --version
# MySQLの起動
sudo systemctl start mysqld.service
# 起動確認
systemctl status mysqld.service
# サーバー起動時にMySQLを自動起動するよう設定
sudo systemctl enable mysqld.service
以下のコマンドで、mysqlのユーザーとDBを作成する。
# 初期パスワードを確認する
sudo cat /var/log/mysqld.log
# MySQLへ接続する(上記で確認したパスワードを入力する)
mysql -u root -p
# パスワードを変更する(変更しないと他のエラーになる)
ALTER USER 'root'@'localhost' IDENTIFIED BY '新パスワード';
# DBを作成する
CREATE DATABASE db_name;
# ユーザーを作成する(ユーザ名とパスワードは自由に設定してください)
CREATE USER 'myapp'@'%' IDENTIFIED BY 'password';
# 作成したユーザーにすべての操作権限を付与
GRANT ALL ON db_name.* TO 'myapp'@'%';
# 設定の反映
FLUSH PRIVILEGES;
マイグレーションとマイグレートを行う。
python3 manage.py makemigrations
python3 manage.py migrate
ここで、mysqlの認証方法の違いでエラーが出ることがある。
mysql8からは認証方法が変更されているらしいので、今回使うDBにも変更をかけてあげてからマイグレーションとマイグレートをするとうまくいく。
alter user 'user_name'@'localhost' identified WITH mysql_native_password by 'password';
一度gunicornを立ち上げて見てみる。
以下のコマンドを打ち、パブリックIP:8000にアクセスし、画面が表示されればOK。
アプリによってはCSSは反映されてなくて良い。
sudo gunicorn リポジトリ名.wsgi --bind=0.0.0.0:8000
フロント周りのビルドを行う
nvmをインストールしてnodejsとnpmを使用できるようにする。
ここで注意が必要なのは、nodeのversionは16以下にしないと動かない。
(AWSが今は最新のversionに対応していないらしい。)
# nvmをインストールする
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
# nvmを有効にする
. ~/.nvm/nvm.sh
# nodejsをインストールする
nvm install node
# version16をインストールする
nvm install 16
# version16を使うように設定する
nvm use 16
package.jsonのあるフォルダまで行き、以下を実行する。
npm install
# 各自で設定したビルドコマンドを実行する
npm run build
ビルドをする際に、ディレクトリへのアクセス権限が無くてエラーになった場合、以下のコマンドでユーザーに権限を付与するとうまくいく。
sudo chown -R user_name ディレクトリへのパス
gunicornの設定を行う
設定ファイルの作成・編集
以下のコマンドで設定ファイルを作成(編集)する。
sudo vi /etc/systemd/system/gunicorn.service
sudo vi /etc/systemd/system/gunicorn.socket
gunicorn.serviceの中身
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
Type=notify
# the specific user that our service will run as
# ここのユーザ名とグループ名はデーモンを実行するユーザを入れる。
# 特に何も考えていなければec2-userにする。
User=ec2-user
Group=ec2-user
# another option for an even more restricted service is
# DynamicUser=yes
# see http://0pointer.net/blog/dynamic-users-with-systemd.html
RuntimeDirectory=gunicorn
# Djangoプロジェクトのパスを入れる
WorkingDirectory=/home/ec2-user/mysite
# gunicornの実行ファイルのあるパスと、プロジェクトのアプリの名前.wsgi
ExecStart=/usr/local/bin/gunicorn mysite_app_name.wsgi
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
[Install]
WantedBy=multi-user.target
gunicorn.socketの中身
[Unit]
Description=gunicorn socket
[Socket]
# sockファイルを作る場所を入れる。基本はdjangoプロジェクトのパスを入れておく。
ListenStream=/home/ec2-user/mysite/mysite_app_name.sock
# Our service won't need permissions for the socket, since it
# inherits the file descriptor by socket activation
# only the nginx daemon will need access to the socket
# gunicorn.serviceと同じユーザを入れる
SocketUser=ec2-user
# Optionally restrict the socket permissions even more.
# SocketMode=600
[Install]
WantedBy=sockets.target
gunicornの起動
sudo systemctl start gunicorn.service
sudo systemctl enable gunicorn
# ちゃんとプロセスが動いていることを確認する。
sudo systemctl status gunicorn
nginxの設定を行う
まずは動くかどうかのテスト
nginxを起動して、パブリックIPにアクセスしてみる。
nginxの画面が表示されればOK。nginxを終了する。
# nginxを起動する
systemctl start nginx
# nginxを終了する
systemctl stop nginx
nginxの設定ファイルを作成・編集
以下のコマンドでnginx.confを編集する。
sudo vi /etc/nginx/nginx.conf
nginx.confの中身
# 全文は多すぎるので省略。userをnginxからec2-userなどのサービスを動かすユーザーへ変える。
...
user ec2-user;
...
# httpブロック内などに、この一行があるか確認する。書いてあればOK。
include /etc/nginx/conf.d/*.conf;
...
以下のコマンドで/etc/nginx/conf.d/mysite.confを作成・編集する。
これは新規作成であり、ファイル名はなんでも良い。
sudo vi /etc/nginx/conf.d/mysite.conf
mysite.confの中身
server {
listen 80;
# ドメインあるいはIPアドレスを設定する
server_name *.*.*.*;
# djangoの静的ファイルの置き場所を指定する。
location /static {
alias /home/ec2-user/mysite/static;
}
# djangoのadmin用の静的ファイルの置き場所を指定する。
location /static/admin {
alias /home/ec2-user/mysite/static/admin;
}
# gunicorn起動時に作成されるsockファイルの場所を指定する。
location / {
proxy_pass http://unix:/home/ec2-user/mysite/mysite_app_name.sock;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
nginxを起動する
以下のコマンドでnginxを起動する。
sudo systemctl start nginx
# すでに起動していた場合はsudo systemctl restart nginx
# プロセスが適切に動いていることを確認する
sudo systemctl status nginx
動いているかブラウザで確認する
パブリックIPにアクセスしてしっかり動いているかを確認する。
CSSが当たっていない場合、mysite.confの「location /static」のパスが間違っている可能性がある。
正しくブラウザで動いていたら完了。
Discussion