背景
Python/Djangoで開発をすすめるにあたり、よく使うコマンドをまとめておきます。
先人たちの知恵をお借りするなどして解決できたことを、この場をお借りして感謝するとともに、大変恐縮ですが自分のメモとしても、こちらへまとめておきます。
環境
(本番環境)
- AWS EC2 (Amazon Linux 2)
- Python 3.7.9 ※2020/12/10時点のAmazon Linux2でのデフォルト
- Django 3.1.3
- PostgreSQL 11.5 ※同上
- Nginx 1.12 ※同上
- Gunicorn
- Putty 0.74
(開発環境)
- Windwos 10 Pro
- Python 3.9.0
- Django 3.1.3
- PostgreSQL 13.1
- Nginx 1.19.5
- Gunicorn
- Putty 0.74
前提
WEBサーバー、APサーバー、DBサーバーを、Amazon EC2(Elastic Computing Cloud) : Amazon Linux 2 で構築します。
- EC2インスタンスへSSH接続した状態で、以降のコマンドを実行します。
※ PuTTY を利用して、Amazon EC2(Elastic Compute Cloud)へ接続する際は、「PuTTY を使用した Windows から Linux インスタンスへの接続」をご参照ください。
【Python/Django】よく使うコマンドのまとめ(4)-前編- <本番運用:Amazon EC2 (Amazon Linux 2)>も併せてご参照ください。
9. 環境変数を設定する。
9-1. 環境変数を設定するファイルを開きます。
$ vi ~/.bash_profile
9-2. 環境変数を設定します。
「i」キー押下で編集可能になります。
編集後は「esc」キー押下し「:wq」と入力すると、内容が保存され、編集が終了します。
(保存せずに終了する場合は「:q!」と入力します。)
(...略...)
export DJANGO_SECRET_KEY='<Djnagoプロジェクト作成時に付与されれるSECRET_KEY(50桁)>'
export DJANGO_SETTINGS_MODULE=<プロジェクト名>.settings
export DB_USER=<任意のユーザー名>
export DB_PASSWORD=<任意のパスワード>
export ALLOWED_HOSTS=<Elastic IP>(もしくは、<独自ドメイン名>) ※
export AWS_SES_ACCESS_KEY_ID=<Amazon SESの利用設定時に取得したAccess key ID>
export AWS_SES_SECRET_ACCESS_KEY=<Amazon SESの利用設定時に取得したSecret Access key>
9-3. 編集した内容を有効にするために、下記を実行します。
$ source ~/.bash_profile
9-4. 環境変数の内容を確認します。
$ env
(...略...)
XDG_SESSION_ID=514
HOSTNAME=ip-XXX-XXX-XXXX-XXX.ap-northeast-1.compute.internal
AWS_SES_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=XXX.XXX.XXX.XXX 57002 22
DJANGO_SECRET_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
SSH_TTY=/dev/pts/0
USER=<任意のユーザー名>
AWS_SES_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX
(...中略...)
ALLOWED_HOSTS=<独自ドメイン名>
MAIL=/var/spool/mail/<任意のユーザー名>
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/<任意のユーザー名>/.local/bin:/home/<任意のユーザー名>/bin
PWD=/home/<任意のユーザー名>
DJANGO_SETTINGS_MODULE=<プロジェクト名>.settings
DB_PASSWORD=<任意のパスワード>
LANG=ja_JP.UTF-8
HISTCONTROL=ignoredups
SHLVL=1
HOME=/home/<任意のユーザー名>
LOGNAME=<任意のユーザー名>
DB_USER=<任意のユーザー名>
SSH_CONNECTION=XXX.XXX.XXX.XXX 57002 XXX.XXX.XXX.XXX 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/1001
_=/usr/bin/env
10. 静的ファイルを配信用ディレクトリへ配置する。
APサーバーの負荷軽減のため、静的ファイルはWEBサーバー(Nginx)から返します。
10-1. 静的ファイル配置ディレクトリを作成し、所有者を<任意のユーザー名>へ変更します。
$ sudo mkdir -p /usr/share/nginx/html/static 静的ファイル用
$ sudo chown <任意のユーザー> /usr/share/nginx/html/static
$ sudo mkdir /usr/share/nginx/html/media メディアファイル用
$ sudo chown <任意のユーザー> /usr/share/nginx/html/media
10-2. Python仮想環境へ入り、manage.pyが存在するディレクトリにて、下記を実行します。
(前提):
STATIC_ROOT = 'usr/share/nginx/html/static'
下記の実行により、/usr/share/nginx/static
ディレクトリに、cssや、jpgなどの静的ファイルが配置されます。
(venv_<プロジェクト名>)$ python manage.py collectstatic
236 static files copied to '/usr/share/nginx/html/static'.
11. DBマイグレーションを行なう。
Python仮想環境へ入り、manage.pyが存在するディレクトリにて、下記を実行します。
(venv_<プロジェクト名>)$ python manage.py migrate
12. Nignxをインストールし、設定を行なう。
12-1. Nginxのインストール
$ amazon-linux-extras list | grep nginx
38 nginx1=latest enabled [ =stable ]
nginx1 がインストール可能な最も高いバージョンであることが分かりました。
下記を実行してインストールします。
$ sugo amazon-linux-extras install nginx1
12-2. Nginxの設定
Nginx用の設定ファイルを編集し、環境設定を行ないます。
「i」キー押下で編集可能になります。
編集後は「esc」キー押下し「:wq」と入力すると、内容が保存され、編集が終了します。
(保存せずに終了する場合は「:q!」と入力します。)
$ sudo vi /etc/nginx/nginx.conf
(...略...)
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name <Elastic IP もしくは 独自ドメイン名>;
return 301 https://$host/$request_uri;
}
# Setting for a TLS enabled server.
server {
listen 443;
listen [::]:443;
server_name <Elastic IP もしくは 独自ドメイン名>;
root /usr/share/nginx/html;
ssl_certificate "/etc/letsencrypt/live/<独自ドメイン>/fullchain.pem";
ssl_certificate_key "/etc/letsencrypt/live/<独自ドメイン>/privkey.pem";
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location /static {
alias /usr/share/nginx/html/static;
}
location /media {
alias /usr/share/nginx/html/media;
}
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-proto $scheme;
proxy_pass http://127.0.0.1:8000;
}
location /.well-known/acme-challenge {
root /usr/share/nginx/html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
(...略...)
12-3. Nginxの自動起動設定
$ sudo systemctl enable nginx.service
12-4. Nginxの起動
$ sudo systemctl start nginx.service
$ systemctl status nginx.service
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: active (running) since 木 2020-12-10 08:20:46 JST; 2 days ago
Process: 13919 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Process: 13916 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 13915 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Main PID: 13922 (nginx)
CGroup: /system.slice/nginx.service
├─13922 nginx: master process /usr/sbin/nginx
└─13923 nginx: worker process
12-5. Nginxの再起動
Nginxを再起動する場合は、下記を実行します。
$ sudo systemctl reload nginx.service
12-6. Nginxの停止
もしも、Nginxを停止する場合は、下記を実行します。
$ sudo systemctl stop nginx.service
13. Gunicornを操作する。
Python仮想環境へ入り、manage.pyが存在するディレクトリにて、下記を実行します。
13-1. Gunicornの起動
(venv_プロジェクト名)$ gunicorn --bind 127.0.0.1:8000 <プロジェクト名>.wsgi -D
(venv_プロジェクト名)$ ps ax | grep gunicorn
671 pts/0 S+ 0:00 grep --color=auto gunicorn
13937 ? S 0:26 /home/<任意のユーザー名>/venv_<プロジェクト名>/bin/python3 /home/<任意のユーザー名>/venv_<プロジェクト名>/bin/gunicorn --bind 127.0.0.1:8000 <プロジェクト名>.wsgi -D
13940 ? S 0:03 /home/<任意のユーザー名>/venv_<プロジェクト名>/bin/python3 /home/<任意のユーザー名>/venv_<プロジェクト名>/bin/gunicorn --bind 127.0.0.1:8000 <プロジェクト名>.wsgi -D
13-2. Gunicornの停止
もしも、Gunicornを停止する場合は、下記を実行します。
(venv_プロジェクト名)$ pkill gunicorn
14. HTTPS化を行なう
【Nginx】Let’sEncryptからのSSL証明書がcertbot-autoで取得できない際の対処 をご参照ください。
15. バッチの定期実行を設定する。
15-1. (例)データベースのバックアップを行なう。
import csv
import datetime
import os
from django.conf import settings
from django.core.management.base import BaseCommand
from ...models import Post
class Command(BaseCommand):
help = "Backup Database"
def handle(self, *args, **options):
date = datetime.date.today().strftime("%Y%m%d")
file_path = settings.BACKUP_PATH + 'database_' + date + '.csv'
os.makedirs(settings.BACKUP_PATH, exist_ok=True)
with open(file_path, 'w') as file:
writer = csv.writer(file)
header = [field.name for field in Post._meta.fields]
writer.writerow(header)
blogs = Post.objects.all()
for customer in customers:
writer.writerow([str(customer.id,
customer.name,
customer.address,
str(customer.phone_number),
str(customer.created_at),
str(customer.updated_at)])
files = os.listdir(settings.BACKUP_PATH)
if len(files) >= settings.NUM_SAVED_BACKUP:
files.sort()
os.remove(settings.BACKUP_PATH + files[0])
BACKUP_PATH ="backup/"
NUM_SAVED_BACKUP = 30
15-2. cron機能を用いて定期実行の設定を行なう。
cron は、登録しておいたコマンドを自動で定期実行してくれるプログラムです。
Amazon Linux 2 に初めから組み込まれている機能です。
「i」キー押下で編集可能になります。
編集後は「esc」キー押下し「:wq」と入力すると、内容が保存され、編集が終了します。
(保存せずに終了する場合は「:q!」と入力します。)
$ crontab -e
0 4 * * * source ~/venv_<プロジェクト名>/bin/activate; cd ~/venv_<プロジェクト名>/<プロジェクト名>; python manage.py backup_db > ~/cron.log 2>&1
cronの基本書式
<分> <時> <日> <月> <曜日> <コマンド>
上記例は、毎日の午前4時00分(UTC)にコマンドを実行する例です。
<注意事項>
cron形式での指定はタイムゾーンがUTCのみで変更できません。
日本標準時(JST)での設定とするには、UTCに対して「-9時間」(9時間を引いた)の値を指定します。
従いまして、上記例は毎日の午後1時(13時)(JST)にコマンドを実行する例となります。
※ DBのバックアップのほか、必要に応じて、SSL証明書(Let's Encrypt)の自動更新、Google pingの発行(サイトマップ.xmlの送信)などを設定すると良いでしょう。
16. Djangoのセキュリティチェックを行なう。
HTTPS化が済んだのちに行ないます。
Python仮想環境へ入り、manage.pyが存在するディレクトリにて、下記を実行します。
# security.W004
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
# security.W006
SECURE_CONTENT_TYPE_NOSNIFF = True
# security.W007
SECURE_BROWSER_XSS_FILTER = True
# security.W008
SECURE_SSL_REDIRECT = True
# security.W012
SESSION_COOKIE_SECURE = True
# security.W016
CSRF_COOKIE_SECURE = True
# security.W019
X_FRAME_OPTIONS = 'DENY'
# security.W021
SECURE_HSTS_PRELOAD = True
(venv_<プロジェクト名>)$ python manage.py check --deploy
WARNINGメッセージが表示されるようであれば、何かしらのセキュリティ対策が不十分とのことです。
通常、上記、プロジェクト設定ファイル(settings.py)の設定内容で、WARNINGは表示されません。
(関連)
【Python/Django】よく使うコマンドのまとめ(1) <仮想環境、プロジェクト、アプリケーションの作成>
【Python/Django】よく使うコマンドのまとめ(2) <パッケージのインストール>
【Python/Django】よく使うコマンドのまとめ(3) <PostgreSQLの操作>
【Python/Django】よく使うコマンドのまとめ(4)-前編- <本番運用:Amazon EC2 (Amazon Linux 2)>
(編集後記)
本番運用時のみならず、開発環境としてEC2を利用することもできますので、Dockerの利用も併せて検討していきたいです。