1.はじめに
IBM Cloudの Virtual Private Cloud(VPC)の仮想インスタンスにPythonのアプリケーションフレームワークであるDjangoのアプリケーションを起動するまでの手順になります。
Django自体、もう目新しいものではありませんが、アプリケーションを評価したい時に、その時のバージョンで、すぐに作れるように、改めて動作を確認した結果として新規に投稿します。
今回は、VPCの仮想インスタンスで、Webサーバ、DBサーバを作成した後、Djangoのはじめての Django アプリ作成で作成する「簡単な投票 (poll) アプリケーション」をデプロイし動作を確認するところまでの流れになります。
2.システム構成
IBM Cloudの東京リージョンにVPCを作成し、ゾーン東京1に2つの仮想インスタンスを作成しています。
役割
-
仮想インスタンス1(外部アクセスからのアクセス可能)
- Webサーバ
- OS: Ubuntu 20.04
- Webサーバ : Djangoのrunserver
- Python : 3.8.5
- Django : 4.0.7
- Webサーバ
-
仮想インスタンス2(外部アクセスからのアクセス不可)
- DBサーバ
- OS: Ubuntu 20.04
- PostgreSQL : 12
- DBサーバ
Virtual Private Cloud(VPC)と仮想インスタンスの作成は、下記のQiita記事を参考に構築しました。
3.作成するアプリケーションのイメージ
このアプリは、Djangoのはじめての Django アプリ作成で作成する「簡単な投票 (poll) アプリケーション」で
今日の天気を投票してもらうサンプルデータを作成して、実行しています。
4.構築手順
Ubuntuの初期設定
- Webサーバ・DBサーバ共通作業
-
リモートサーバへのログイン
まずはリモートサーバにログインします。※クライアントでの作業 ssh -i [秘密鍵のファイル名] root@[WEBサーバのIPアドレス]
(注)DBサーバーは、フローティングIPを設定していないため、外部からSSHでログインすることができません。
Webサーバーに、DBサーバーに接続するための秘密鍵を配置して、DBサーバにSSHでログインします。※Webサーバでの作業 $ ssh -i [秘密鍵のファイル名] root@[DBサーバのIPアドレス]
-
ユーザー作成
VPCの仮想インスタンスの初期状態では一般ユーザーが存在しない為、作業用のsudo ができる一般ユーザーを作成します。$ adduser [ユーザー名] $ gpasswd -a [ユーザー名] sudo
ユーザーが作成できたら、作成したユーザーにスイッチして、作成ユーザーにて作業を行います。
$ su - [ユーザー名]
-
パッケージの一覧更新
パッケージリストの更新を実行$ sudo apt-get update
Python(周辺モジュール)、PostgreSQLクライアント導入
- Webサーバーでの作業
- Python3、pip、PostgreSQLのクライアントのインストール
Python3、pip、PostgreSQLへ接続するためのクライアントをインストールします。$sudo apt-get install python3-pip python3-dev libpq-dev postgresql-client-12
PostgreSQL導入
- DBサーバーでの作業
-
PostgreSQLをインストールします。
$ sudo apt-get install postgresql postgresql-contrib
-
PostgreSQLのバージョンとPostgreSQLが起動していることを確認します。
Ubuntu 20.04ではPostgreSQL Version12が導入されます。$ psql --version psql (PostgreSQL) 12.12 (Ubuntu 12.12-0ubuntu0.20.04.1)
$ sudo systemctl status postgresql ● postgresql.service - PostgreSQL RDBMS Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled) Active: active (exited) since Fri 2022-09-30 15:05:10 UTC; 2min 33s ago Main PID: 3642 (code=exited, status=0/SUCCESS) Tasks: 0 (limit: 9508) Memory: 0B CGroup: /system.slice/postgresql.service Sep 30 15:05:10 poll-db systemd[1]: Starting PostgreSQL RDBMS... Sep 30 15:05:10 poll-db systemd[1]: Finished PostgreSQL RDBMS.
-
PostgreSQLにDBと接続ユーザーを作成します。
PostgreSQLのデータベースにログインします。
$ sudo su - postgres $ psql psql (12.12 (Ubuntu 12.12-0ubuntu0.20.04.1)) Type "help" for help.
DBの作成
postgres=# CREATE DATABASE polls; CREATE DATABASE
PostgreSQLのユーザーの作成(Djangoから接続するためのユーザー、パスワード)
postgres=# CREATE USER poll_user WITH PASSWORD 'poll_password'; CREATE ROLE
作成したユーザーに権限追加
postgres=# GRANT ALL PRIVILEGES ON DATABASE polls TO poll_user; GRANT
DBからログアウト
postgres=# \q
-
PostreSQLの設定ファイル(postgresql.conf)を変更します。
listen_addressesの設定がデフォルトでは、 localhostのみlistenしている状態なので、 DBサーバ外部からも接続できるようにlisten_addressesを「 * 」に変更します。
$ cd /etc/postgresql/12/main/ $ vi postgresql.conf
- 変更前 (60行目)
#listen_addresses = 'localhost' # what IP address(es) to listen on;
- 変更後 (60行目)
listen_addresses = '*' # what IP address(es) to listen on;
-
PostgreSQLの設定ファイル(pg_hba.conf)を変更。
WebサーバからPostgreSQLに接続できるようにpg_hba.confに Webサーバのサブネット(例:10.10.0.0/24 )からmd5認証で接続できるように設定を追加します。$ vi pg_hba.conf
- 追加内容(末尾)
host all all 10.10.0.0/24 md5
-
postgresqlユーザーから 作業用ユーザーに戻ります。
$ exit logout
-
PostgreSQLを再起動して設定を反映します。[作業ユーザーで実行]
$ sudo systemctl restart postgresql
PostgreSQLの状態を確認すると設定ミスがない限りは起動しているはずです。
$ sudo systemctl status postgresql ● postgresql.service - PostgreSQL RDBMS Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled) Active: active (exited) since Sun 2022-10-02 02:44:42 UTC; 7s ago Process: 16723 ExecStart=/bin/true (code=exited, status=0/SUCCESS) Main PID: 16723 (code=exited, status=0/SUCCESS) Oct 02 02:44:42 poll-db systemd[1]: Starting PostgreSQL RDBMS... Oct 02 02:44:42 poll-db systemd[1]: Finished PostgreSQL RDBMS.
接続確認(WebサーバからPostgreSQLまで)
- Webサーバーでの作業
PostgreSQLサーバの設定が終わったので、WebサーバからPostgreSQLサーバへの接続を確認します。
-
PostgreSQLのpsqlクライアントが導入されていることを確認します。
導入されていれば、 Version 12であることが確認できます。 psqlのコマンドがない場合は、 Ubuntuの初期設定の最初から確認してください。$ psql --version psql (PostgreSQL) 12.12 (Ubuntu 12.12-0ubuntu0.20.04.1)
-
psqlコマンドを使ってPostgreSQLのDBに接続します。
$ psql -h [PostgreSQLサーバのIPアドレス] -U [PostgreSQLのユーザー名] [DB名] Password for user poll_user: [パスワード入力]
正常にDBに接続できたなら、以下の様にプロンプトが表示されます。
psql (12.12 (Ubuntu 12.12-0ubuntu0.20.04.1)) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help.
-
DBに接続できているか、「 ¥l 」 コマンドを実行して、DBの一覧を表示します。
template0、template1、postgresqlに加えて、作成したDB(例: polls)が出力されることを確認してください。
polls=> \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+---------+---------+------------------------ polls | postgres | UTF8 | C.UTF-8 | C.UTF-8 | =Tc/postgres + | | | | | postgres=CTc/postgres + | | | | | poll_user=CTc/postgres postgres | postgres | UTF8 | C.UTF-8 | C.UTF-8 | template0 | postgres | UTF8 | C.UTF-8 | C.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | C.UTF-8 | C.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres (4 rows)
これで、WebサーバからDBサーバの接続まで構築が完了しました。 次からは、Django環境を作成します。
Djangoの環境作成
- Webサーバでの作業
-
pipコマンドを使って、Djangoと PythonからPostgreSQLに接続するためのアダプタ「psycopg2」をインストールします。
$ sudo pip3 install Django==4.0.7 psycopg2
今回、Djangoは、バージョン4.0.7を指定して導入しましたが、導入可能なバージョンの一覧は、以下の出力の様に、存在しないバージョンを存在しない文字列を入力して、
$ sudo pip3 install Django==4.xxxx ERROR: Could not find a version that satisfies the requirement Django==4.xxxx (from versions: 1.1.3, 1.1.4, 1.2, 1.2.1, 1.2.2, 1.2.3, 1.2.4, 1.2.5, 1.2.6, 1.2.7, 1.3, 1.3.1, 1.3.2, 1.3.3, 1.3.4, 1.3.5, <<省略>> 3.2.14, 3.2.15, 4.0a1, 4.0b1, 4.0rc1, 4.0, 4.0.1, 4.0.2, 4.0.3, 4.0.4, 4.0.5, 4.0.6, 4.0.7, 4.1a1, 4.1b1, 4.1rc1, 4.1, 4.1.1) ERROR: No matching distribution found for Django==4.xxxx
Djangoアプリケーションの準備
今回は、Djangoのはじめての Django アプリ作成で作成する「簡単な投票 (poll) アプリケーション」を使って動作確認を行います。
古いソースコードですが、Githubの DigitalOcean Community
に「簡単な投票 (poll) アプリケーション」があったので、このソースコードを使用します。
-
「簡単な投票 (poll) アプリケーション」を GitHubのリポジトリからクローンします。
$ git clone https://github.com/do-community/Django-polls.git
-
クローンが完了すると
Django-polls
フォルダが作成されます。 今回は/app
フォルダで動作させたいので、Django-polls
を/app
フォルダに変更し、フォルダの権限も作業ユーザー
(例: dai.dai)に変更します。$ sudo mv Django-polls /app $ sudo chown -R dai.dai /app
設定が完了すると/appのフォルダ構成は以下のように、Djangoのプロジェクトのファイルで構成されています。
$ ls -l /app total 24 -rw-rw-r-- 1 dai dai 1079 Oct 2 02:50 LICENSE -rw-rw-r-- 1 dai dai 1359 Oct 2 02:50 README.md -rwxrwxr-x 1 dai dai 538 Oct 2 02:50 manage.py drwxrwxr-x 2 dai dai 4096 Oct 2 02:50 mysite drwxrwxr-x 5 dai dai 4096 Oct 2 02:50 polls drwxrwxr-x 3 dai dai 4096 Oct 2 02:50 templates
settings.pyの設定(Djangoの設定ファイル)
Djangoの設定ファイル settings.py
を編集します。
変更箇所は、次の3つのパラメーターです。
- SECRET_KEY
- ALLOWED_HOSTS
- DATABASE
-
secret_keyの再生成
SECRET_KEYは、パラメータは、以下の様に解除されているので、再生成します。
SECRET_KEY = 'your_secret_key_here'
Django の管理用のスクリプト manage.py を使ってShellを起動します。
$ python3 manage.py shell Python 3.8.10 (default, Jun 22 2022, 20:18:18) [GCC 9.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>>
Shellが起動したら以下の内容を実行して、secret_keyの再生成を行います。
from Django.core.management.utils import get_random_secret_key secret_key = get_random_secret_key() text = 'SECRET_KEY = \'{0}\''.format(secret_key) print(text)
出力された内容をsettyngs.pyのSECRET_KEYの値に記入します。
- 変更前
SECRET_KEY = 'your_secret_key_here'
- 変更後
SECRET_KEY = 'xxxtx!u3j@ix8h59_xxxbjc8u1l_y+f&d%_l!rc_cus@ua9xxx'
-
ALLOWED_HOSTS (アクセス許可設定)
デフォルトでは
[]
ローカルホストのみ接続許可になっているので、
全て許可の*
、もしくはWebサーバのIPアドレスを設定します。- 変更前
ALLOWED_HOSTS = []
- 変更後
※全て許可の場合 ALLOWED_HOSTS = ['*'] *IPアドレス指定の場合 ALLOWED_HOSTS = ['111.222.333.444']
-
DATABASE設定
DjangoからDBに接続するための設定を行います。初期設定ではsqlite3
が設定されているのでPostgreSQLの設定に変更します。- 変更前
DATABASES = { 'default': { 'ENGINE': 'Django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
- 変更後
DATABASES = { 'default': { 'ENGINE': 'Django.db.backends.postgresql_psycopg2', 'NAME': 'DB名', 'USER': 'PostgreSQLの接続ユーザー名', 'PASSWORD': 'PostgreSQLの接続ユーザーのパスワード', 'HOST': 'DBの接続先IPアドレス', 'PORT': '接続先のPostgresQLのポート番号', } }
マイグレーションの実行
-
Djangoのマイグレーションを実行し、DBのスキーマーを生成します。
$ python3 manage.py migrate
コマンドを実行すると以下の様に,出力され、最後に
Applying
の文字列が続きます。何も出力されない場合は、DBへの接続できてない場合が想定されます。settings.pyの設定を見直してください。System check identified some issues: WARNINGS: polls.Choice: (models.W042) Auto-created primary key used when not defining a primary key type, by default 'Django.db.models.AutoField'. HINT: Configure the DEFAULT_AUTO_FIELD setting or the PollsConfig.default_auto_field attribute to point to a subclass of AutoField, e.g. 'Django.db.models.BigAutoField'. polls.Question: (models.W042) Auto-created primary key used when not defining a primary key type, by default 'Django.db.models.AutoField'. HINT: Configure the DEFAULT_AUTO_FIELD setting or the PollsConfig.default_auto_field attribute to point to a subclass of AutoField, e.g. 'Django.db.models.BigAutoField'. Operations to perform: Apply all migrations: admin, auth, contenttypes, polls, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying auth.0012_alter_user_first_name_max_length... OK Applying polls.0001_initial... OK Applying sessions.0001_initial... OK
Djangoのスーパーユーザーの登録
Djangoのスーパーユーザーを登録します。ここで作成したユーザーは、「簡単な投票 (poll) アプリケーション」の管理画面にログインする時に使用します。
$ python3 manage.py createsuperuser
Username (leave blank to use 'dai'): [ユーザー名を入力]
Email address: [メールアドレスを入力]
Password: [パスワードを入力]
Password (again): [パスワードを入力]
Superuser created successfully.
デモデータの作成
これから起動する「簡単な投票 (poll) アプリケーション」のデモデータを作成します。
今回は、以下の様に、今日の天気を投票してもらうデータを作成します。
- 今日の天気
- 質問: 今日の天気は?
- 回答: 1.雨、2.曇り、3.晴れ
-
Django の管理用のスクリプト manage.py を使ってShellを起動します。
$ python3 manage.py shell
-
Shellの中で以下の内容を実行して、DBにデータを登録します。
from polls.models import Choice, Question from Django.utils import timezone q = Question(question_text="今日の天気", pub_date=timezone.now()) q.save() q.question_text = "今日の天気は?" q.save() q.choice_set.create(choice_text='雨', votes=0) q.choice_set.create(choice_text='曇り', votes=0) q.choice_set.create(choice_text='晴れ', votes=0) exit
これで、準備が終わりました。あとは、Webサーバを起動するだけです!
動作確認:Webサーバーの起動
-
Djangoのrunserver[テスト用簡易サーバ]を使って起動します。
0.0.0.0:8000はどこのIPアドレスからでも、8000番ポートで受け付けるという意味です。$ python3 manage.py runserver 0.0.0.0:8000
正常に起動すると以下の様に
Starting development server・・・
とメッセージが出力されます。System check identified 2 issues (0 silenced). October 02, 2022 - 03:05:12 Django version 4.0.7, using settings 'mysite.settings' Starting development server at http://0.0.0.0:8000/ Quit the server with CONTROL-C.
-
ブラウザで WebサーバのフローティングIPアドレスを使って次のURLで 「 http://(フローティングIPアドレス):8000/polls 」アクセスします。
問題がなければブラウザに以下の画像のように「 今日の天気は? 」とメッセージが表示されるはずです。下記、赤矢印に沿って画面遷移を続けてと投票を継続すると投票数が増えていくことを確認できます。
ブラウザアクセスをしている時のコンソールでは、以下の様にアクセスログが流れているのを確認できます。
[03/Oct/2022 15:38:07] "GET /polls/ HTTP/1.1" 200 549
[03/Oct/2022 15:38:07] "GET /static/polls/style.css HTTP/1.1" 404 179
[03/Oct/2022 15:38:07] "GET /polls/1/ HTTP/1.1" 200 945
[03/Oct/2022 15:38:07] "POST /polls/1/vote/ HTTP/1.1" 302 0
[03/Oct/2022 15:38:07] "GET /polls/1/results/ HTTP/1.1" 200 568
[03/Oct/2022 15:38:07] "GET /polls/1/ HTTP/1.1" 200 945
[03/Oct/2022 15:38:08] "POST /polls/1/vote/ HTTP/1.1" 302 0
[03/Oct/2022 15:38:08] "GET /polls/1/results/ HTTP/1.1" 200 568
[03/Oct/2022 15:38:08] "GET /polls/1/ HTTP/1.1" 200 945
[03/Oct/2022 15:38:08] "POST /polls/1/vote/ HTTP/1.1" 302 0
[03/Oct/2022 15:38:08] "GET /polls/1/results/ HTTP/1.1" 200 568
[03/Oct/2022 15:38:08] "GET /polls/1/ HTTP/1.1" 200 945
[03/Oct/2022 15:38:09] "GET /polls/ HTTP/1.1" 200 549
5.最後に
これで、IBM Cloudの Virtual Private Cloud(VPC)の仮想インスタンスで Djangoのアプリケーションを動かすことができました。
次のステップとして、インフラ視点、アプリ視点での可視化・モニタリングに挑戦した時のQiita記事を作成しました。以下のQiita記事も併せてご一読ください。
- インフラ視点での可視化・モニタリング
- アプリ視点での可視化・モニタリング
※Djangoのアプリケーションを動かすWebサーバとして Djangoの runserverを使用しましたが、 uWSGI やGunicornでの動作は、別の投稿で書きたいと思います。