1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Django】EC2(CentOS7)+Django+apache+mod_wsgiでデプロイしてみた

Last updated at Posted at 2021-05-03

#はじめに
タイトルの通りですが、Djangoで開発したサイトをapache+mod_wsgiで公開する手順をまとめました。

もの凄くハマってしまい時間がかかったので、
実際のデプロイまでの手順を記載しておきます。

なお、Macでの手順になりますので、Windowsの方は途中の手順が異なります。

##前提
・プロジェクトは開発済みであること
・GitHubアカウントがあること
・AWSアカウントがあること

#GitHubにプロジェクトを置く
GitHubのマイページでリポジトリを作成します。

+を押しNew repositoryを選択

スクリーンショット 2021-05-02 13.17.45.jpg

リポジトリ名を入力し、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の画面を開きます。

左上のサービスをクリックしEC2を選択します。
スクリーンショット 2021-05-02 13.28.32.jpg

サイドメニューでインスタンスを選択します。

その後、上のメニューからインスタンスを起動をクリックします。
スクリーンショット 2021-05-02 13.29.52.jpg

左のタブでAWS Marketplaceをクリックします。
(1回で画像の画面が表示されない場合は何回かクリックしてみたください。)

CentOS7を見つけたら、右側にある選択をクリックします。
スクリーンショット 2021-05-02 13.31.38.jpg

右下Continueをクリック

・ステップ 2: インスタンスタイプの選択
無料利用枠の対象にチェックがついてのを確認し、
右下の次のステップ:インスタンスの詳細の設定ボタンをクリック

・ステップ3:インスタンスの詳細の設定
特に何もしないで次のステップへ

・ステップ4:ストレージの追加
特に何もしないで次のステップへ

・ステップ5:タグの追加
特に何もしないで次のステップへ

・ステップ6:セキュリティグループの設定
ルールの追加を押すと1行追加されるのでタイプをHTTPにしてください。
スクリーンショット 2021-05-02 13.41.13.jpg

その後、確認と作成をクリックし起動をクリックします。
すると、下記の画面が出てきます。
スクリーンショット 2021-05-02 13.44.18.jpg

新しいキーペアの作成を選択し、キーペア名を入力します。
そんなに悩まずに決めてしまって大丈夫です。

入力後にキーペアのダウンロードをクリックすると、
自分の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です。

スクリーンショット 2021-05-02 12.29.32.jpg

#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を選択後に内容をコピーします。
スクリーンショット 2021-05-02 14.39.57.jpg

クローンします。

$ 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のところに入力します。

私はエラーが発生してしまいましたー...。
スクリーンショット 2021-05-03 13.44.42.jpg

ただ、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()

ブラウザをリロードすると無事表示されました。
(結構ハマってしまいました・・・。)
スクリーンショット 2021-05-03 15.42.33.jpg

#さいごに

以上でデプロイすることができました!

もしかしたら上手くいかない方もいるかもしれませんがエラーを見て解決してみてください!

私は途中わからないことがあったのでMENTAを使いました。
便利なので同じく躓いた方は是非ご利用ください。

単発質問でどなたかに質問すれば解決できると思います。

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?