Djangoをサーバーへデプロイして、ブラウザからアクセスできるようにします。
後編では、ソースをアップロードして、
サーバーで動作するようになるまでをやってみます。
システムの概要やDjango・サーバーの下準備は前編でご紹介しています。
Djangoのソースをアップロードする
zipファイルにしたDjangoのソースをEC2へアップロードします
筆者はTeratermを使用して、サーバーへec2-userでssh接続して、
zipファイルをTeratermのウインドウへドラッグ&ドロップします
すると、以下のウインドウが現れ、「OK」を押してアップロードします
zipファイルを解凍し、フォルダを移動させる
※ここからはrootユーザーに切り替えます。
また、Djangoのプロジェクト名はdjango_practiceとします。
(実行手順)
- rootユーザーに切り替える
1sudo su - zipファイルを解凍する
123456# zipファイルがあることを確認するll# zipファイルを解凍するunzip <Djangoプロジェクトのzipファイル># zipファイルと解凍されたフォルダが存在することを確認するll - 解凍したフォルダを /var/www/ へ移動する
123456# フォルダを /var/www/ へコピーするcp -r <解凍したフォルダ> /var/www/# /var/www/ へ移動するcd /var/www/# フォルダを移動できているか確認するll
(実行結果)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
[root@ip-×××-××-××-×× ec2-user]# ll total 376 -rw-r--r-- 1 ec2-user ec2-user 383985 Oct 30 20:19 django_practice.zip [root@ip-×××-××-××-×× ec2-user]# unzip django_practice.zip Archive: django_practice.zip creating: django_practice/accounts/ extracting: django_practice/accounts/__init__.py extracting: django_practice/accounts/admin.py inflating: django_practice/accounts/apps.py creating: django_practice/accounts/migrations/ extracting: django_practice/accounts/migrations/__init__.py inflating: django_practice/accounts/models.py creating: django_practice/accounts/templates/ creating: django_practice/accounts/templates/accounts/ inflating: django_practice/accounts/templates/accounts/login.html inflating: django_practice/accounts/templates/accounts/signup.html ----------略------------------------------------------------------------ [root@ip-×××-××-××-×× ec2-user]# ll total 376 drwxr-xr-x 8 root root 220 Oct 31 00:44 django_practice -rw-r--r-- 1 ec2-user ec2-user 383985 Oct 30 20:19 django_practice.zip [root@ip-×××-××-××-×× ec2-user]# cp -r django_practice /var/www/ [root@ip-×××-××-××-×× ec2-user]# cd /var/www/ [root@ip-×××-××-××-×× www]# ll total 0 drwxr-xr-x 8 root root 220 Oct 31 00:45 django_practice |
Pythonコマンドのエイリアスを設定する
ここで、Pythonのバージョンを確認します。
1 2 3 4 |
[root@ip-×××-××-××-×× ~]# python -V Python 3.9.12 [root@ip-×××-××-××-×× ~]# pip --version pip 22.0.4 from /usr/local/lib/python3.9/site-packages/pip (python 3.9) |
後のことを考えるとpythonのバージョンは3系のほうがいいので、
2系のバージョンの方はエイリアスを設定しましょう
1 2 3 4 5 6 7 8 9 10 |
# python->python3となるよう設定する echo 'alias python=python3' >> ~/.bashrc # pip->pip3となるよう設定する echo 'alias pip=pip3' >> ~/.bashrc # .bashrcを読み込んで、エイリアスを読み込む source ~/.bashrc # pythonのバージョン確認 python -V # pipのバージョン確認 pip --version |
Python のライブラリをインストールする
前編で作成したrequirements.txt を使用して、ライブラリをインストールします
1 2 3 4 5 6 |
# Djnagoプロジェクトのルートディレクトリへ移動 cd django_practice # ライブラリをインストール pip install -r requirements.txt # インストール後、確認 pip list |
PostgreSQLの設定をする
ライブラリをインストールする
DjnagoでPostgreSQLを使用するためのライブラリをインストールしましょう
1 |
pip install psycopg2 |
Django用のPostgreSQLユーザー&DBを作成する
Djangoの下準備として、settings/production.py に記載したユーザーを作成します
私の場合は
1 2 3 4 5 6 7 8 9 10 11 |
# PostgreSQLを使用するようにする DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql_psycopg2", "NAME": "djangodatabase", # データベース名 "USER": "djangouser", # ユーザー名 "PASSWORD": "djangopassword", # パスワード "HOST": "localhost", "PORT": "5432", } } |
に合うように設定していきます
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# PostgreSQLにログイン [root@ip-×××-××-××-×× django_practice]# psql -U postgres -d postgres Password for user postgres: psql (14.3) Type "help" for help. # ユーザー作成 postgres=# CREATE USER djangouser WITH PASSWORD 'djangopassword'; CREATE ROLE postgres=# ALTER ROLE djangouser SET CLIENT_ENCODING TO 'utf8'; ALTER ROLE postgres=# ALTER ROLE djangouser SET DEFAULT_TRANSACTION_ISOLATION TO 'read committed'; ALTER ROLE postgres=# ALTER ROLE djangouser SET TIMEZONE TO 'Asia/Tokyo'; ALTER ROLE # DBの作成 postgres=# CREATE DATABASE djangodatabase; CREATE DATABASE # djangouser と djangodatabase を紐づける postgres=# GRANT ALL PRIVILEGES ON DATABASE djangodatabase TO djangouser; GRANT # ログアウト postgres=# \q # 作成したユーザーとDBにアクセスしてみる [root@ip-×××-××-××-×× django_practice]# psql -U djangouser -d djangodatabase Password for user djangouser: psql (14.3) Type "help" for help. djangodatabase=> # ログアウトする djangodatabase=> \q |
DjangoのDBをマイグレーションする
1 |
python manage.py migrate --settings=django_practice.settings.production |
スーパーユーザーを作成する
1 2 3 4 5 6 7 8 9 10 |
[root@ip-×××-××-××-×× django_practice]# python manage.py createsuperuser --settings=django_practice.settings.production ユーザー名 (leave blank to use 'root'): admin メールアドレス: admin@admin.com Password: Password (again): このパスワードは ユーザー名 と似すぎています。 このパスワードは短すぎます。最低 8 文字以上必要です。 このパスワードは一般的すぎます。 Bypass password validation and create user anyway? [y/N]: y Superuser created successfully. |
staticファイルを作成する
WEBサーバー(Nginx)に静的ファイルを管理させるために、
静的ファイルを1か所に集めます
(実行コマンド&結果)
1 2 3 |
[root@ip-×××-××-××-×× django_practice]# python manage.py collectstatic --settings=django_practice.settings.production 206 static files copied to '/usr/share/nginx/html/static'. |
STATIC_ROOTに指定したディレクトリに静的ファイルがコピーされたので、見てみましょう
1 |
ll -R /usr/share/nginx/html/static |
Gunicornをインストールする
ライブラリをインストールする
1 2 3 4 5 6 7 8 |
[root@ip-×××-××-××-×× django_practice]# pip install gunicorn Collecting gunicorn Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB) qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq 79.5/79.5 KB 9.8 MB/s eta 0:00:00 Requirement already satisfied: setuptools>=3.0 in /usr/local/lib/python3.9/site-packages (from gunicorn) (58.1.0) Installing collected packages: gunicorn Successfully installed gunicorn-20.1.0 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv |
Gunicornを使用してDjangoを起動する
1 2 3 4 5 |
[root@ip-×××-××-××-×× django_practice]# gunicorn djangosnippets.wsgi --bind=0.0.0.0:8000 --env DJANGO_SETTINGS_MODULE=django_practice.settings.production [2022-11-01 00:44:39 +0900] [29221] [INFO] Starting gunicorn 20.1.0 [2022-11-01 00:44:39 +0900] [29221] [INFO] Listening at: http://0.0.0.0:8000 (29221) [2022-11-01 00:44:39 +0900] [29221] [INFO] Using worker: sync [2022-11-01 00:44:39 +0900] [29222] [INFO] Booting worker with pid: 29222 |
ブラウザからアクセスしてみる
http://<パブリックIPアドレス or DNS>:8000/admin
にアクセスします
cssは後で効くようにするので、ご心配なく
一応、スーパーユーザーでログインしてみます。
ログインできました
ここで、いったん gunicornを Ctrl+c で停止しておきます
Djangoをサービスに登録する
ここでは3つのファイルを作成し、Djangoをサービス化します
- socketファイル
Nginxとの接続設定を行うための設定ファイル - gunicorn.conf.py
gunicornの設定ファイル - serviceファイル
Djangoとの接続設定を行うための設定ファイル
socketファイル
/etc/systemd/system/ に <Djangoプロジェクト名>.socket を作成します
vi コマンドで socket ファイルを作ります
1 |
vi /etc/systemd/system/<Djangoプロジェクト名>.socket |
i を押して、INSERTモードにし、下記を記入します
1 2 3 4 5 6 7 8 9 10 11 |
[Unit] # socketファイルの説明 Description=gunicorn socket [Socket] # serviceファイルのポート番号を指定(今回はsockファイルを指定) ListenStream=/var/run/<Djangoプロジェクト名>.sock [Install] # 必ず「sockets.target」を指定 WantedBy=sockets.target |
EscキーでINSERTモードを抜け、「:wq!」で保存します。
cat コマンドでファイルの中身を確認します
1 |
cat /etc/systemd/system/<Djangoプロジェクト名>.socket |
gunicorn.conf.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# gunicorn.conf.py を入れるフォルダを作成 mkdir /etc/gunicorn # 作成したフォルダへ移動 cd /etc/gunicorn # gunicorn.conf.pyを作成 vi gunicorn.conf.py # 先ほどと同じ要領でファイルを作成します -----gunicorn.conf.py のなかみ-------------------- # # Gunicorn config file # wsgi_app = '<Djangoプロジェクト名>.wsgi:application' # Server Mechanics #======================================== # current directory chdir = '/var/www/<Djangoプロジェクト名>' # daemon mode daemon = False # enviroment variables raw_env = [ 'DJANGO_SETTINGS_MODULE=<Djangoプロジェクト名>.settings.production', ] # Server Socket #======================================== bind = '0.0.0.0:8000' # Worker Processes #======================================== workers = 2 # Logging #======================================== # access log accesslog = '/var/log/gunicorn/access.log' access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' # gunicorn log errorlog = '-' loglevel = 'info' ----------------------------------------------------- # 中身を確認 cat gunicorn.conf.py # ログ用のフォルダ作成 mkdir /var/log/gunicorn |
confファイル内のパラメータに関しては下記をご参考ください
serviceファイル
まず、whichコマンドでgunicornコマンドのパスを調べます
1 2 |
[root@ip×××-××-××-×× gunicorn]# which gunicorn /usr/local/bin/gunicorn |
筆者の場合は、/usr/local/bin/gunicorn でした
これをもとにserviceファイルを作成します
1 2 3 4 5 |
# serviceファイルの作成 vi /etc/systemd/system/<Djangoプロジェクト名>.service # なかみの確認 cat /etc/systemd/system/<Djangoプロジェクト名>.service |
(serviceファイルのなかみ)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[Unit] # serviceファイルの説明 Description=gunicorn daemon # serviceファイルの起動時に、socketファイルの起動を要求 Requires=<Djangoプロジェクト名>.socket # 必ず「network.target」を指定 After=network.target [Service] # Djangoプロジェクトを指定(manage.pyがあるディレクトリ) WorkingDirectory=/var/www/<Djangoプロジェクト名> # 通信開始時に起動するコマンドを設定 # 先ほど調べたgunicornコマンドのパスを使用 ExecStart=/usr/local/bin/gunicorn --config /etc/gunicorn/gunicorn.conf.py <Djangoプロジェクト名>.wsgi:application Restart=always [Install] # 必ず「multi-user.target]を指定 WantedBy=multi-user.target |
サービス化できているか確認する
1 2 3 4 5 6 7 8 9 10 |
# 先ほど作成したファイルを systemd に反映します systemctl daemon-reload # サービスの起動&ステータス確認 systemctl start <Djangoプロジェクト名.>service systemctl status <Djangoプロジェクト名>.service # 自動起動設定 sudo systemctl enable <Djangoプロジェクト名>.service sudo systemctl is-enabled <Djangoプロジェクト名>.service |
(実行結果)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[root@ip-×××-××-××-×× gunicorn]# systemctl daemon-reload [root@ip-×××-××-××-×× gunicorn]# systemctl start django_practice.service [root@ip-×××-××-××-×× gunicorn]# systemctl status django_practice.service ● django_practice.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/django_practice.service; disabled; vendor preset: disabled) Active: active (running) since Wed 2022-11-02 01:17:04 JST; 5s ago Main PID: 7398 (gunicorn) CGroup: /system.slice/django_practice.service tq7398 /usr/local/bin/python3.9 /usr/local/bin/gunicorn --config /etc/gunicorn/gunicorn.conf.py django_practice.wsgi:application tq7399 /usr/local/bin/python3.9 /usr/local/bin/gunicorn --config /etc/gunicorn/gunicorn.conf.py django_practice.wsgi:application mq7400 /usr/local/bin/python3.9 /usr/local/bin/gunicorn --config /etc/gunicorn/gunicorn.conf.py django_practice.wsgi:application Nov 02 01:17:04 ip-×××-××-××-××.ap-northeast-1.compute.internal systemd[1]: Started gunicorn daemon. Nov 02 01:17:04 ip-×××-××-××-××.ap-northeast-1.compute.internal gunicorn[7398]: [2022-11-02 01:17:04 +0900] [7398] [INFO] Starting gunicorn 20.1.0 Nov 02 01:17:04 ip-×××-××-××-××.ap-northeast-1.compute.internal gunicorn[7398]: [2022-11-02 01:17:04 +0900] [7398] [INFO] Listening at: unix:/var/r...7398) Nov 02 01:17:04 ip-×××-××-××-××.ap-northeast-1.compute.internal gunicorn[7398]: [2022-11-02 01:17:04 +0900] [7398] [INFO] Using worker: sync Nov 02 01:17:04 ip-×××-××-××-××.ap-northeast-1.compute.internal gunicorn[7398]: [2022-11-02 01:17:04 +0900] [7399] [INFO] Booting worker with pid: 7399 Nov 02 01:17:05 ip-×××-××-××-××.ap-northeast-1.compute.internal gunicorn[7398]: [2022-11-02 01:17:05 +0900] [7400] [INFO] Booting worker with pid: 7400 Hint: Some lines were ellipsized, use -l to show in full. [root@ip-×××-××-××-×× gunicorn]# systemctl enable django_practice.service Created symlink from /etc/systemd/system/multi-user.target.wants/django_practice.service to /etc/systemd/system/django_practice.service. [root@ip-×××-××-××-×× gunicorn]# systemctl is-enabled django_practice.service enabled |
NginxがDjangoにアクセスするように設定
confファイルの作成
1 2 3 4 |
cd /etc/nginx mkdir sites-available cd sites-available/ vi <Djnagoプロジェクト名> |
confファイルのなかみ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
server { # 設定しているウェブサイトへのリクエストを通すポート listen 80; # ウェブサイトのIPもしくはドメイン名 # EIPを設定しいない場合は, localhost と設定 server_name <IP or ドメイン>; # ファビコンが見つからないというエラーを回避するおまじない location = /favicon.ico {access_log off; log_not_found off;} ### 以下、リクエストURLとNGINX上のパスとの対応を定義 # Django静的ファイルへのパスを設定 location /static { alias /usr/share/nginx/html/static; } location /media { alias /usr/share/nginx/html/media; } # リクエストをウェブページに流すためにunixソケットへのパスを設定 location / { # djangapp.sockにリクエスト結果を流している proxy_pass http://unix:/var/run/<Djangoプロジェクト名>.sock; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Forwarded-Proto $scheme; } } |
シンボリックリンクを作成する
先ほど作成したファイルのシンボリックリンクを
/etc/nginx/sites-enabled/ に貼ります
これになんの意味があるかというと、
/etc/nginx/sites-available/:Nginxのconfファイルを置いておく(読み込まない)
/etc/nginx/sites-enabled/:ここにあるconfファイルを読み込む
なので、confファイルは /etc/nginx/sites-available/ に作成しておき、
読み込ませたいconfファイルをシンボリックリンクで制御します
1 2 3 4 5 6 7 8 9 |
# /etc/nginx/sites-enabled を作成 mkdir /etc/nginx/sites-enabled cd /etc/nginx/sites-enabled # confファイルのシンボリックリンクを作成 ln -s /etc/nginx/sites-available/<Djangoプロジェクト名> <Djangoプロジェクト名> ll # ↓のように表示されればOK! # lrwxrwxrwx 1 root root 41 Nov 3 00:58 <Djangoプロジェクト名> -> /etc/nginx/sites-available/<Djangoプロジェクト名> |
/etc/nginx/sites-enabled/内のファイルを読み込ませる
1 2 3 4 5 6 7 8 9 |
# バックアップを作成する cp -a /etc/nginx/nginx.conf /etc/nginx/nginx.conf.`date +%Y%m%d` # ファイルを編集する vi /etc/nginx/nginx.conf include /etc/nginx/conf.d/*.conf; の下に include /etc/nginx/sites-enabled/*; と追記 |
これでNginxが/etc/nginx/sites-enabled/内のファイルを読み込むようになります
confファイルのテストをする
1 2 3 |
[root@ip-×××-××-××-×× nginx]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful |
テストに成功したのでNginxとDjangoのアプリを再起動します
1 2 3 4 |
systemctl restart nginx systemctl status nginx systemctl restart <Djangoプロジェクト名> systemctl status <Djangoプロジェクト名> |
ブラウザからアクセスしてみる
http://<パブリックIPアドレス or DNS>/admin
にアクセスしてみます
管理画面が開き、ついでにcssも効いています
これで、デプロイ完了です
大変でしたが、Django以外の勉強になったので、よかったです!!
ソースの更新方法ややり残したことをおまけ編にまとめました
時間があれば、ご一読ください
参考文献
コメント