#はじめに
タイトルの通りですが、Djangoで開発したサイトをapache+mod_wsgiで公開する手順をまとめました。
もの凄くハマってしまい時間がかかったので、
実際のデプロイまでの手順を記載しておきます。
なお、Macでの手順になりますので、Windowsの方は途中の手順が異なります。
##前提
・プロジェクトは開発済みであること
・GitHubアカウントがあること
・AWSアカウントがあること
#GitHubにプロジェクトを置く
GitHubのマイページでリポジトリを作成します。
+
を押しNew repository
を選択
リポジトリ名を入力し、Private
を選択しCreate repository
をクリックします。
Privateでなくても大丈夫ですが、他の方に見られたくない内容もpushするためPrivateにしています。
gitignoreで指定すればいい話ですがそちらは各自で行ってください・・・。
プロジェクトをGitHubにpushします。
$ cd プロジェクト配下
$ ls
プロジェクト名 アプリ名 manage.py
$ git init
$ git add *
$ git commit -m "first commit"
$ git remote add origin https://github.com/<アカウント名>/<リポジトリ名>.git #GitHubのHTTPSをコピペでOKです。
$ git push -u origin master
GitHubのWebページを更新して自分のプロジェクトの内容が反映されていたらOKです。
結構ざっくり記載しましたが、
もしできなかった方がいた際はご自身で調べていただけますと幸いです。
#EC2でインスタンス作成
AWCのEC2の画面を開きます。
サイドメニューでインスタンスを選択します。
その後、上のメニューからインスタンスを起動
をクリックします。
左のタブでAWS Marketplace
をクリックします。
(1回で画像の画面が表示されない場合は何回かクリックしてみたください。)
CentOS7を見つけたら、右側にある選択をクリックします。
右下Continue
をクリック
・ステップ 2: インスタンスタイプの選択
無料利用枠の対象にチェックがついてのを確認し、
右下の次のステップ:インスタンスの詳細の設定
ボタンをクリック
・ステップ3:インスタンスの詳細の設定
特に何もしないで次のステップへ
・ステップ4:ストレージの追加
特に何もしないで次のステップへ
・ステップ5:タグの追加
特に何もしないで次のステップへ
・ステップ6:セキュリティグループの設定
ルールの追加
を押すと1行追加されるのでタイプをHTTP
にしてください。
その後、確認と作成
をクリックし起動をクリックします。
すると、下記の画面が出てきます。
新しいキーペアの作成を選択し、キーペア名を入力します。
そんなに悩まずに決めてしまって大丈夫です。
入力後にキーペアのダウンロード
をクリックすると、
自分のPCのダウンロードフォルダにキーペアがダウンロードされます。
ダウンロードされていることを確認したら、インスタンスの作成
をクリックし、
先ほどのインスタンスの画面に戻ると新しくインスタンスが登録されているはずです。
##サーバにアクセスする方法
ターミナルを開きます。
現在のディレクトリは下記の状態です。
$ pwd
/Users/<ユーザ名>
現在のディレクトリ配下を確認します。
.ssh
が存在することを確認してください。
$ ls -al
drwx------ 6 <ユーザ名> staff 192 4 30 16:45 .ssh
※存在しない場合は下記の通り作成し、再度確認してください。
.ssh
にディレクトリを作成します。
ls -al
でkeysが存在することを確認します。
$ mkdir .ssh/keys
$ ls -al .ssh/
drwxr-xr-x 3 <ユーザ名> staff 96 4 30 16:45 keys
drwxr-xr-x
でなかった場合は下記コマンドを実行
$ chmod 755 .ssh/keys
先ほどダウンロードしたキーペアをkeys配下に移動します。
cp -p コピー元 コピー先
です。
$ cp -p <ダウンロードフォルダ>/<キーペア(拡張子は.pem)> .ssh/keys
$ ls .ssh/keys/
<先ほどコピーしたキーペアが表示されること>
コピーではなくファイルを移動する場合は下記コマンドを実行します。
mv コピー元 コピー先
です。
mv <ダウンロードフォルダ>/<キーペア(拡張子は.pem)> .ssh/keys
$ ls .ssh/keys/
<先ほどコピーしたキーペアが表示されること>
サーバにアクセスします。
IPアドレスは、EC2のインスタンスを開き、パブリック IPv4 アドレス
に記載されているIPアドレスをコピーします。
$ ssh centos@<IPアドレス> -i .ssh/keys/<キーペア>
#Python3.6のインストール
サーバに接続後にインストール作業を行います。
エラーがでた際は対処してください。
基本的にエラーは出ないはずです!
Pythonのバージョン確認します。
$ python -V
Python 2.7.5
RPMを持ってきます。
$ sudo yum install -y https://repo.ius.io/ius-release-el7.rpm
インストールします。
$ sudo yum -y install python36u
$ sudo yum -y install python36u-pip
$ sudo yum -y install python36u-devel
再度バージョン確認をします。
※ Python 3.6.**になっていること
$ python3.6 -V
Python 3.6.8
#apacheのインストール
apacheを使うのに必要なパッケージをインストールします。
$ sudo yum install -y httpd
$ sudo yum install -y httpd httpd-devel
インストールパスを確認します。
パスが確認できれば正常にインストールできています。
$ which httpd
/usr/sbin/httpd
apacheを起動します。
$ sudo systemctl start httpd
apacheの自動起動を有効化します。
$ sudo systemctl enable httpd
Created ~
firewallの状態確認をします。
現在はapacheを起動しているだけでfirewallが動作しているとユーザがサーバにアクセスできません。
しかし、firewallはデフォルトでインストールされていないこともあるのでサービスの状態を確認してみます。
$ sudo systemctl status firewalld
Unit firewalld.service could not be found.
ユニットfirewalld.serviceが見つかりませんでした。
と言っているのでインストールされていません。気にせず進みましょう。
ブラウザにアクセス
EC2のインスタンスを開きます。
-> パブリック IPv4 アドレスに記載されているIPアドレスをコピーします。
-> ブラウザのURLの部分にhttp://<IPアドレス>
を入力します。
IPアドレスの部分は先ほどコピーしたものです
下の画面が出ればOKです。
#Djangoを動かす
現在のディレクトリの確認をします。
CentOSだとデフォルトで下記の状態のはずです。
$ pwd
/home/centos
ここからは開発者によってフォルダの場所などが変わるらしいですが、私は下記の手順で行います。
ディレクトリを作成し、cd
します。
$ mkdir public_html
$ ls
public_html
ホームディレクト内のディレクトリ使う場合は、
ホームディレクトリそのもののパーミッションで他ユーザの実行権限つけないと動かないらいしので
パーミッションを変更します。
$ chmod 701 /home/centos
パーミッションを確認します。
centosのパーミッションがdrwx-----x.
になっていればOKです。
$ ls -al /home/
drwxr-xr-x. 3 root root 20 May 2 02:46 . #ここは気にしない
dr-xr-xr-x. 17 root root 224 Feb 29 2020 .. #ここは気にしない
drwx-----x. 6 centos centos 119 May 2 03:38 centos
ディレクトリを移動します。
$ cd ~/public_html/
$ pwd
/home/centos/public_html
今回は仮想環境を使ってDjangoを動かします。
python3.6で仮想環境を作ると仮想環境上のpythonは3.6を指すようになるらしいです。
venvを作りcd
します。
$ python3.6 -m venv pyenv
$ ls
pyenv
$ cd pyenv
$ pwd
/home/centos/mypy/pyenv
仮想環境に変えます。
$ source ./bin/activate
下記のように先頭に(pyenv)がつけばOKです。
(pyenv) [centos@ip-172-31-34-15 pyenv]$
バージョン確認します。
$ python -V
Python 3.6.8
先ほどのpython -V
の結果とは異なって3.6.8に変化していました。OKです。
pipのアップグレードを行います。
$ pip install --upgrade pip
Djangoをインストールします。
$ pip install django
Djangoのバージョン確認をします。
3.0以上になるはずです。
$ python -m django --version
3.2
#mod_wsgiのインストール
mod_wsgiをインストールする前にgccをインストールします。
※仮想環境上で行ってください。
$ sudo yum install -y gcc
mod_wsgiをインストールします。
$ pip install mod_wsgi
入ったモジュールのパスを表示します。
出力されたパスは後で使うのでメモしておきます。
$ find /home/centos/public_html/ -name 'mod_*.so'
/home/centos/public_html/pyenv/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
仮想環境を抜けます。
先頭の(pyenv)
が消えるはずです。
$ deactivate
##設定ファイル作成
apachに読ませるDjangoの設定を行います。
$ sudo vi /etc/httpd/conf.d/django.conf
pyenvの箇所は仮想環境名なので、
違う環境名にした方はそちらを記載してください。
<プロジェクト名>には、各自のDjangoで開発したプロジェクトの名前を記載します。
画面に何も表示されていない状態になるので、
a
を押し-- INSERT --
が表示されていることを確認したら下記を入力します。
※誤字のないように!
LoadModule wsgi_module /home/centos/public_html/pyenv/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
WSGIPythonHome /home/centos/public_html/pyenv
WSGIScriptAlias / /home/centos/public_html/pyenv/<プロジェクト名>/<プロジェクト名>/wsgi.py
WSGIPythonPath /home/centos/public_html/pyenv/lib/python3.6/site-packages
<Directory /home/centos/public_html/pyenv/<プロジェクト名>/<プロジェクト名>>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
入力したら、escキー
を押し、:wq
を入力後Enter
を押します。
入力に失敗して保存したくない場合は、
escキー
を押し、:q!
を入力後Enter
を押し、再度viの箇所から始めます。
ファイルを作れているか確認します。
先ほどの入力値がでてくればOKです。
$ cat /etc/httpd/conf.d/django.conf
LoadModule wsgi_module /home/centos/public_html/pyenv/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
WSGIPythonHome /home/centos/public_html/pyenv
WSGIScriptAlias / /home/centos/public_html/pyenv/<プロジェクト名>/<プロジェクト名>/wsgi.py
WSGIPythonPath /home/centos/public_html/pyenv/lib/python3.6/site-packages
<Directory /home/centos/public_html/pyenv/<プロジェクト名>/<プロジェクト名>>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
#gitのインストール
git cloneコマンドを使うため、gitをインストールします。
gitのインストールに必要なものをインストールします。
$ sudo yum -y install gcc curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker autoconf
インストール先ディレクトリに移動します。
$ cd /opt/
$ pwd
/opt
圧縮ファイルをダウンロードします。
$ sudo wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.9.5.tar.gz
sudo: wget: command not found
と出力された方は下記を実行してから再度実行します。
$ sudo yum -y install wget
フォルダ内の確認をします。
$ ls
git-2.9.5.tar.gz
圧縮ファイルを解凍します。
$ sudo tar xzvf git-2.9.5.tar.gz
圧縮ファイルを削除します。
$ sudo rm git-2.9.5.tar.gz
解凍先ディレクトに移動します。
$ cd git-2.9.5/
makeコマンドでインストールします。
$ sudo make prefix=/usr/local all
バージョンを確認します。
$ git --version
git version 2.24.4
#プロジェクトのクローンを作成
ディレクトを移動します。
$ cd /home/centos
現在のディレクトリを確認します。
$ pwd
/home/centos
$ ls
public_html
GitHubのCodeをクリックし、HTTPSを選択後に内容をコピーします。
クローンします。
$ git clone <先ほどのコピーしたURL>
ユーザ名を聞かれるので入力します。
パスワードを聞かれるので入力します。
クローンを確認します。
$ ls
public_html <プロジェクト>
プロジェクトを移動します。
$ mv <プロジェクト>/ public_html/pyenv/
$ ls public_html/pyenv/
bin <プロジェクト> include lib lib64 pip-selfcheck.json pyvenv.cfg
#PostgreSQLのインストールと設定
今回のDjangoのプロジェクトではPostgreSQLを使っているので、
そこら辺の設定を行います。(忘れてました。)
$ sudo yum -y install postgresql-server
初期化コマンドを実行します。
/var/lib/pgsql/dataに設定ファイルなどが配置されます。
$ sudo postgresql-setup initdb
ファイルの設定変更を行います。
$ sudo -s
$ cd /var/lib/pgsql/data/
$ cp -p postgresql.conf postgresql.conf.org
$ echo "listen_addresses = '*'" >> /var/lib/pgsql/data/postgresql.conf
$ cp -p pg_hba.conf pg_hba.conf.org
$ echo "# PostgreSQL Client Authentication Configuration File" > ./pg_hba.conf
$ echo "# ===================================================" >> ./pg_hba.conf
$ echo "local all all trust" >> ./pg_hba.conf
$ echo "host all all 127.0.0.1/32 trust" >> ./pg_hba.conf
$ echo "host all all ::1/128 trust" >> ./pg_hba.conf
$ exit
サービスを再起動します。
$ sudo service postgresql restart
Redirecting to /bin/systemctl restart postgresql.service
サービスの自動起動を有効にします。
$ sudo systemctl enable postgresql
local接続の可否を確認します。
$ psql -U postgres -h 127.0.0.1 -w
psql (9.2.24)
Type "help" for help.
postgres=#
データベースを作成します。
;
を最後につけ忘れないように注意
postgres=# CREATE DATABASE <データベース名>;
CREATE DATABASE
データベース一覧を確認します。
postgres-# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+-----------+-------------+-------+-----------------------
<作ったやつ>| postgres | SQL_ASCII | ja_JP.UTF-8 | C |
postgres | postgres | SQL_ASCII | ja_JP.UTF-8 | C |
template0 | postgres | SQL_ASCII | ja_JP.UTF-8 | C | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | SQL_ASCII | ja_JP.UTF-8 | C | =c/postgres +
| | | | | postgres=CTc/postgres
(4 rows)
ユーザを作成します。
パスワードは' '(シングルクォーテーション)
で囲むのを忘れずに!
postgres-# CREATE USER centos WITH PASSWORD '<パスワード>'
CREATE ROLE
postgresから抜ける
postgres-# \q
#プロジェクトとPostgreSQLの連携
仮想環境に移動します。
$ cd /home/centos/public_html/pyenv
$ source ./bin/activate
プロジェクトに移動します。
$ cd <プロジェクト名>
psycopg2のインストールをします。
$ pip install psycopg2
インストールできない場合は下記のインストールをしてみてください。
$ sudo yum -y install postgresql-devel
$ sudo yum install python-devel
$ sudo yum -y install python-psycopg2
makemigrationの実行
$ python manage.py makemigrations
Migrations for 'diary_app':
diary_app/migrations/0001_initial.py
- Create model Category
- Create model Post
- Create model Like
ここでエラーが出る方はもしかしたらcloneしたプロジェクト内のmigrationsに
すでにファイルが存在している可能性があります。
それがあると、整合性が取れずにエラーになりますので、
migrationsディレクトリ配下の__init__.py以外のファイルを移動しましょう。
移動はmv <移動元のPATH> <移動先のPATH>
で行えます。
migrateの実行
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, 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 sessions.0001_initial... OK
superuserの作成
$ python manage.py createsuperuser
ユーザー名 (leave blank to use 'centos'): admin
メールアドレス:
Password:
Password (again):
Superuser created successfully.
#apacheの再起動
$ sudo setsebool -P httpd_enable_homedirs 1
$ sudo setsebool -P httpd_unified 1
$ sudo systemctl restart httpd
#アクセス
ブラウザでアクセスをしてみる
http://をURLのところに入力します。
ただ、Test 1.2.3の画面から切り替わっているのでエラーを解決すれば表示できそう?
ということで、エラーを確認してみます。
$ sudo tail /var/log/httpd/error_log
[Mon May 03 04:42:39.635978 2021] [wsgi:error] [pid 14563] (13)Permission denied: [client 119.173.210.88:50914] mod_wsgi (pid=14563, process='', application='ip-172-31-34-15.ap-northeast-1.compute.internal|'): Call to fopen() failed for '/home/centos/public_html/pyenv/diary/diary/wsgi.py'.
[Mon May 03 04:42:39.733301 2021] [mime_magic:error] [pid 14562] [client 119.173.210.88:50913] AH01512: mod_mime_magic: can't read `/home/centos/public_html/pyenv/diary/diary/wsgi.py', referer: http://52.199.97.95/
[Mon May 03 04:42:39.733445 2021] [mime_magic:error] [pid 14562] [client 119.173.210.88:50913] AH01512: mod_mime_magic: can't read `/home/centos/public_html/pyenv/diary/diary/wsgi.py', referer: http://52.199.97.95/
[Mon May 03 04:42:39.764545 2021] [wsgi:error] [pid 14562] (13)Permission denied: [client 119.173.210.88:50913] mod_wsgi (pid=14562, process='', application='ip-172-31-34-15.ap-northeast-1.compute.internal|'): Call to fopen() failed for '/home/centos/public_html/pyenv/diary/diary/wsgi.py'., referer: http://52.199.97.95/
[Mon May 03 04:43:11.997333 2021] [mime_magic:error] [pid 14561] [client 119.173.210.88:50919] AH01512: mod_mime_magic: can't read `/home/centos/public_html/pyenv/diary/diary/wsgi.py'
[Mon May 03 04:43:11.997500 2021] [mime_magic:error] [pid 14561] [client 119.173.210.88:50919] AH01512: mod_mime_magic: can't read `/home/centos/public_html/pyenv/diary/diary/wsgi.py'
[Mon May 03 04:43:12.028730 2021] [wsgi:error] [pid 14561] (13)Permission denied: [client 119.173.210.88:50919] mod_wsgi (pid=14561, process='', application='ip-172-31-34-15.ap-northeast-1.compute.internal|'): Call to fopen() failed for '/home/centos/public_html/pyenv/diary/diary/wsgi.py'.
[Mon May 03 04:43:12.145556 2021] [mime_magic:error] [pid 14565] [client 119.173.210.88:50920] AH01512: mod_mime_magic: can't read `/home/centos/public_html/pyenv/diary/diary/wsgi.py', referer: http://52.199.97.95/
[Mon May 03 04:43:12.145639 2021] [mime_magic:error] [pid 14565] [client 119.173.210.88:50920] AH01512: mod_mime_magic: can't read `/home/centos/public_html/pyenv/diary/diary/wsgi.py', referer: http://52.199.97.95/
[Mon May 03 04:43:12.145724 2021] [wsgi:error] [pid 14565] (13)Permission denied: [client 119.173.210.88:50920] mod_wsgi (pid=14565, process='', application='ip-172-31-34-15.ap-northeast-1.compute.internal|'): Call to fopen() failed for '/home/centos/public_html/pyenv/diary/diary/wsgi.py'., referer: http://52.199.97.95/
英語ばかりでよくわからんです。
[wsgi:error] [pid 14562]
と[mime_magic:error] [pid 14565]
を解決すればいいのかな?
[wsgi:error] [pid 14562]
に関しては、Permission denied
と書いてあるので、
パーミッションが適切でない可能性があります。
[mime_magic:error] [pid 14565]
に関してはmod_mime_magic: can't read
と書いてあるので、
こちらも読み込めませんでした的な感じでしょうか。
アクセス制御あたりを変更してみます。
まず、SELinuxを無効化します。
enforcingをdisabledに変更
SELinuxはroot権限でもアクセス制御することができたりするやつです。
# vi /etc/selinux/config
サーバを再起動します。
# reboot
SELinuxの状態を確認します。
# getenforce
Disabled
次に、wsgi.pyを修正します。
$ vi public_html/pyenv/<プロジェクト名>/<プロジェクト名>/wsgi.py
内容を下記の通りにします。
"""
WSGI config for diary project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
"""
import os
import sys #### 追加 ####
from django.core.wsgi import get_wsgi_application
sys.path.append('/home/centos/public_html/pyenv/<プロジェクト名>') #### 追加 ####
sys.path.append('/home/centos/public_html/pyenv/<プロジェクト名>/<プロジェクト名>/wsgi.py') #### 追加 ####
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '<プロジェクト名>.settings')
application = get_wsgi_application()
ブラウザをリロードすると無事表示されました。
(結構ハマってしまいました・・・。)
#さいごに
以上でデプロイすることができました!
もしかしたら上手くいかない方もいるかもしれませんがエラーを見て解決してみてください!
私は途中わからないことがあったのでMENTAを使いました。
便利なので同じく躓いた方は是非ご利用ください。
単発質問でどなたかに質問すれば解決できると思います。