##概要
詰まりまくったのでメモ。Dockerで開発していたのでそのままデプロイしたろ!と思っていたが意味わからなすぎて断念。(おそらく?)一般的な方法でデプロイした。もっと良い方法があれば教えて欲しい限りです。
##環境
OS: Amazon Linux AMI release 2017.09
ローカル: Docker
Python: 3.6.2
Django: 1.11.5
Gunicorn: 19.7.1
Nginx: 1.12.1
##AWSの設定
###インスタンスの作成
AWSの設定はAmazon Web Services 基礎からのネットワーク&サーバー構築を参考にした。
AWSに登録してコンソール > EC2からインスタンスを作成する。全部デフォルト。t2microなら無料。
VPC、サブネット、ルートテーブル、ゲートウェイ、セキュリティグループやらが作成される(はず)。なかったら作ってVPCに紐付ける。sshキーをダウンロードまたは登録しておく。
###ポートの開放
EC2 > セキュリティグループからポートが開放できる。セキュリティグループを選択 -> インバウンド -> 編集 -> ルールの追加で80番ポート、8000番ポート(確認用、あとで閉じる)を開く。タイプはカスタムTCP、ソースは0.0.0.0/0で良い。
ここで EC2 > インスタンス から作ったインスタンスの詳細が確認できる。右側のパブリックDNSでドメイン、IPv4パブリックIPでIPが確認できる。
##nginxのインストール
AWSにsshでログイン。キーペアをダウンロードした場合は~/.sshに置いて別のキー名を指定する。
# ssh -i ~/.ssh/id_rsa ec2-user@(インスタンスのIP)
以下ではrootで作業する。
$ sudo su -
以下、EC2にNginx + Gunicorn + SupervisorでDjangoアプリケーションをデプロイするを参考にnginxをインストール。
nginx入れる。
$ yum install nginx
nginxを起動する。
$ nginx
nginxの自動起動設定
$ chkconfig --add nginx
$ chkconfig nginx on
自動起動設定できているか確認する。
$ chkconfig | grep nginx
nginx 0:off 1:off 2:on 3:on 4:on 5:on 6:off
また、http://(パブリックDNS)
を確認してnginxが起動しているか確認する。
##Djangoプロジェクトの起動
###AWSにプロジェクトを送る。
scpでzipで固めたDjangoプロジェクトを送る。また送る前にrequirements.txtは用意しておく。
# pip freeze > requirements.txt
# scp -i ~/.ssh/id_rsa ~/path/to/project.zip ec2-user@yourIP:home/ec2-user/
送ったものがhome/ec2-userに落ちているはず。解凍する
$ unzip project.zip
ほんとはgitで落とせばいいんだろうけどプライベートリポジトリにしてるので新しいuser登録して新しくssh登録してってしないといけないのかな。誰か教えてください。
###pythonとかを入れる
色々考えるのがめんどくさかったのでEC2サーバにPython3環境構築を参考にした。
gitとpyenv入れる。-yが全部yesって答えるオプションらしい。初めて知った。
$ yum install git -y
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
path通す。
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
コマンド通るか確認。
$ pyenv -v
依存関係を入れる。
$ sudo yum install gcc zlib-devel bzip2 bzip2-devel readline readline-devel sqlite sqlite-devel openssl openssl-devel -y
本体を入れる。
$ pyenv install 3.6.2
pythonを切り替える。これはrootのpythonなので、sudo su -後でないとデフォルトのpythonに戻ってしまうので注意。
$ pyenv global 3.6.2
$ pyenv rehash
$ python --version
Python 3.6.2
Django、その他諸々のプロジェクトに必要なライブラリをインストールする。
$ pip install --upgrade -r project/requirements.txt
requirements.txtにGunicornが入ってなければGunicornを入れる。
Gunicornとはwsgiサーバーのことで、nginxとDjangoを繋ぐものみたいなイメージ。
$ pip install gunicorn
manage.pyの上でDjangoを起動させる。
$ gunicorn your_project.wsgi --bind=0.0.0.0:8000
http://(パブリックDNS):8000
を確認すると、ALLOWED_HOSTSに追加してね!と出るので追加する。
# 中略
ALLOWED_HOSTS = ['(パブリックDNS)']
# 以下略
もう一回確認してプロジェクトが見えれば成功。
###Nginxの設定の変更
再びEC2にNginx + Gunicorn + SupervisorでDjangoアプリケーションをデプロイするを丸パクリ。本当にありがとうございました
/etc/nginx.confとあるが、Amazon Linuxでは/etc/nginx/nginx.confにあった。
以下引用
/etc/nginx.confを以下の通り編集する
/etc/nginx.conf〜中略〜
http {
〜中略〜upstream app_server {
server 127.0.0.1:8000 fail_timeout=0;
}
server {
#以下4行はコメントアウト
#listen 80 default_server;
#listen [::]:80 default_server;
#server_name localhost;
#root /usr/share/nginx/html;
# 以下3行を追加
listen 80;
server_name IPアドレス or ドメイン;
client_max_body_size 4G;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
# 以下4行を追加
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
〜以下略〜
nginxの再起動
$ service nginx restart
Stopping nginx: [ OK ]
Starting nginx: [ OK ]
Djangoを再びGunicornで立ち上げる
$ gunicorn your_project.wsgi --bind=0.0.0.0:8000
http://(パブリックDNS)
で確認できたら成功。
##daemon化
今はコマンドからGunicornを起動しているだけなので、ログアウトしたら終了してしまう。そこでGunicornをデーモン化して常駐するようにしたい。
ただ色々な所を見ると、Surpervisorというツールでそれが可能なようだが、SurpervisorはPython3系に対応していないので2系の環境をもう一つ作れとのこと。んなアホな。
もうちょっと調べてみると、普通に-Dというオプションをつけるだけでデーモンとして起動できるらしい。
###起動
$ gunicorn your_project.wsgi --bind=0.0.0.0:8000 -D
終了するときは
$ ps -ef | grep gunicorn
root 17419 1 0 Oct07 ? 00:00:08 /root/.pyenv/versions/3.6.2/bin/python3.6 /root/.pyenv/versions/3.6.2/bin/gunicorn your_project.wsgi --bind=0.0.0.0:8000 -D
root 17422 17419 0 Oct07 ? 00:00:01 /root/.pyenv/versions/3.6.2/bin/python3.6 /root/.pyenv/versions/3.6.2/bin/gunicorn your_project.wsgi --bind=0.0.0.0:8000 -D
root 21686 21594 0 08:05 pts/0 00:00:00 grep --color=auto gunicorn
$ kill 17419
###スクリプトで起動
ただこのままだと毎回めんどくさいので、シェルスクリプトでサーバーを起動、停止するにあるスクリプトを使わせてもらう。
Flaskとかで作ったちょっとしたサーバーの起動/停止用のシェルスクリプト。
gunicornでデーモン状態にしている。
startで起動、stopで終了、restartでstop+start。
your_project.sh#!/bin/sh PROGNAME=`basename $0` BASEDIR=`dirname $0` PIDFILE=$BASEDIR/$PROGNAME.pid
start() {
echo "Starting server..."
cd $BASEDIR
gunicorn flaskhello:app -p $PIDFILE -D
}
stop() {
echo "Stopping server..."
kill -TERMcat $PIDFILE
rm -f $PIDFILE
}
usage() {
echo "usage: $PROGNAME start|stop|restart"
}
if [ $# -lt 1 ]; then
usage
exit 255
fi
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
esac
以下のgunicorn flaskhello:app -p $PIDFILE -D
を
gunicorn your_project.wsgi --bind=0.0.0.0:8000 -D
に書き換える。
$ sh your_project.sh start #起動
$ sh your_project.sh stop #終了
$ sh your_project.sh restart #再起動
sshを切ってもhttp://(パブリックDNS)
が見えたら成功。ひとまず見えるようになった。
##staticファイルが見つからない
ただここまで追ってもcss,jsなどstaticファイルは見つかってないはず。以下で見えるようにする。
setting.pyのSTATIC_URL、STATIC_PATHは設定済みでローカルでは見える状態とする。
詳しい解説 -> Django での static files の扱い方まとめ
###staticファイルのコピー
manage.pyの上でstaticファイルを指定したディレクトリにコピー
$ python manage.py collectstatic
###nginx.confをいじる
nginx.confにstaticファイルのディレクトリを登録する。
server{
# 〜中略〜
location /static {
alias /home/ec2-user/your_project/static;
#settings.pyで設定したのと同じ場所を記述
}
# 〜以下略〜
}
###パーミッション変更
ここでnginxとgunicornを再起動する。
$ sh your_project.sh stop
Stopping server...
$ service nginx restart
Stopping nginx: [ OK ]
Starting nginx: [ OK ]
$ sh your_project.sh start
Starting server...
するととpermission deniedが出た。これはec2-userにotherからの権限がないせいだった。
参考によると、このディレクトリに移動する権限が必要らしい。
/home/でec2-userに権限を与える。
$ ls -l
drwx------ 5 ec2-user ec2-user 4096 Oct 6 04:19 ec2-user
$ chmod o+x ec2-user
$ ls -l
drwx-----x 5 ec2-user ec2-user 4096 Oct 6 04:19 ec2-user
gunicornを再起動すると無事にstaticファイルにアクセスできて終了。
##参考
EC2にNginx + Gunicorn + SupervisorでDjangoアプリケーションをデプロイする
EC2サーバにPython3環境構築
シェルスクリプトでサーバーを起動、停止する
Django での static files の扱い方まとめ
Nginxでつくる、どシンプルな静的コンテンツサーバ