Python
Django
CentOS
初心者
さくらVPS

さくらVPSでCentOS7の設定からDjangoのデプロイまで

 Djangoでサイトを作成しようとした際に、デプロイやstaticファイル(CSS/js)の反映あたりで色々詰まったのですが、一元化されている情報源がなかなか見つかりませんでした。

 そこでCentOS7の設定〜Djangoチュートリアルのサイトをデプロイし、staticファイルを反映させるまでの手順をまとめてみました。

Djangoチュートリアルサイトで作成するサンプルアプリ(pollsアプリ)をデプロイするので、このチュートリアルをこなしていることを前提としています。
※ 普段はWebを書く人では無いので、おかしな点などご指摘頂けると幸いです。

環境

  • MacOS X 10.11.6
  • CentOS 7 (さくらVPS)
  • Apache 2.4.6
  • Python 3.6
  • Django 2.0

CentOSの設定

 基本的な設定はCentOS7.x 基本設定メモを参考にしました。

  • 作業用ユーザの作成
VPS
[root@hogehoge ~]# useradd username
[root@hogehoge ~]# passwd username
  • 作成したユーザをwheelグループに追加し、sudoコマンドを許可
VPS
[root@hogehoge ~]# usermod -G wheel username
[root@hogehoge ~]# visudo
## Same thing without a password
# %wheel  ALL=(ALL)       NOPASSWD: ALL
ここの行の#を外す

[root@hogehoge ~]# vi /etc/pam.d/su
#auth           required       pam_wheel.so use_uid
ここの行の#を外す

作成したusernameユーザでログインし、sudo suコマンド等が使える様に。

  • sshの設定

 先にディレクトリを作成。

VPS
[username@hogehoge ~]$ mkdir /home/username/.ssh
[username@hogehoge ~]$ chmod 700 /home/username/.ssh

 mac側での鍵を作成。今回は/Users/usename/.ssh/id_rsa_djangoに指定しました。

Mac
$ ssh-keygen -C 'for_django'
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/username/.ssh/id_rsa): /Users/username/.ssh/id_rsa_django
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
...

VPSに公開鍵持って行く
$ scp ~/.ssh/id_rsa_django.pub username@[VPSのIPアドレス]:/home/username/.ssh

 VPSで公開鍵を設定

VPS
[username@hogehoge ~]$ cd /home/username/.ssh
[username@hogehoge .ssh]$ cat id_rsa_django.pub >>  authorized_keys
[username@hogehoge .ssh]$ chmod 600 authorized_keys

 Mac側でssh接続が可能に。
(sshの接続は/Users/username/.ssh/configに設定を記述しておくと楽ですね。)

Mac
$ ssh -i id_rsa_django username@[VPSのIPアドレス]

 余談ですが、この時、サーバの設定で詰まった際に何度もCentOS7をインストールし直したりしてると

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
...略

みたいなエラーが出ることが。ssh-keygen -R 123.456.789.33(ホストIP)で解決する模様。
→参照:SSH接続で WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! って言われて接続を拒否られるとき

  • sshdの設定
VPS
[username@hogehoge ~]$ sudo vi /etc/ssh/sshd_config

# 以下変更点
# ポート番号を変更
Port 22(任意の数字)
# rootログイン不可
PermitRootLogin no
# pass無し不許可
PermitEmptyPasswords no
# 鍵認証許可
PubkeyAuthentication yes
# pass認証不可
PasswordAuthentication no

# 設定を反映
[username@hogehoge ~]$ sudo systemctl restart sshd.service

  • firewallの設定変更

 firewallの起動と自動起動設定

VPS
[root@hogehoge ~]# systemctl start firewalld.service
[root@hogehoge ~]# systemctl enable firewalld
[root@hogehoge ~]# systemctl status firewalld

 http, https, sshでの外部アクセスの許可

VPS
[root@hogehoge ~]# firewall-cmd --permanent --add-service=http
[root@hogehoge ~]# firewall-cmd --permanent --add-service=https
[root@hogehoge ~]# firewall-cmd --permanent --add-port=1234(任意のポート番号)/tcp
[root@hogehoge ~]# systemctl restart firewalld

 SELinuxを有効にする場合はそちらでも別途設定が必要な様です。
→参照:CentOS7でsshdのポート番号を変更する方法

 基礎的ですがひとまずサーバ設定はこんな感じで。

CentOSにPython、Djangoを入れる

  • Python3とDjangoのインストール

 CentOSにPythonをインストールします。今回はpython3.6を使用する前提で進めます。
→参照:Python3をCentOS7にyumでインストールする手順

VPS
[username@hogehoge ~]$ sudo yum install -y https://centos7.iuscommunity.org/ius-release.rpm
[username@hogehoge ~]$ sudo yum search python36
[username@hogehoge ~]$ sudo yum install python36u
  • venv仮想環境作成
VPS
[username@hogehoge ~]$ python3.6 -m venv venv

# activate
[username@hogehoge ~]$ cd venv/bin
[username@hogehoge ~]$ . activate
(venv)[username@hogehoge ~]$
  • Django2.0のインストール
VPS
(venv)[username@hogehoge ~]$ pip install Django==2.0

デプロイ

 ここではDjango公式サイトのチュートリアルで作成できるpollsアプリをデプロイします。

  • 必要なライブラリをインストール
VPS
[username@hogehoge ~]$ sudo yum install httpd-devel
[username@hogehoge ~]$ sudo yum install python36u-mod_wsgi

 Django2.0のチュートリアルでは↓の様なフォルダ構成になっているかと思います。

sample
├── db.sqlite3
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── polls
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── models.py
    ├── static
    ├── templates
    ├── tests.py
    ├── urls.py
    └── views.py

 settings.pyのALLOW_HOSTSにIPを指定(*では全て許可)。公開するサイトのドメイン名www.example.com等でも可能

mysite/settings.py
ALLOWED_HOSTS = ['*']

 VPS側でdjango_sampleディレクトリを作り、このsampleディレクトリを配置します。今回はGitHubにあげてgit cloneしています。

VPS
[username@hogehoge ~]$ mkdir django_sample
[username@hogehoge ~]$ cd django_sample
[username@hogehoge django_sample]$ git clone https://github.com/userid/sample.git(仮)

# この様なディレクトリ構造になる。
username
├── django_sample
    └── sample
        ├── db.sqlite3
        .
        .
  • DjangoのApache用の設定

 公式サイトのDjangoをApacheとmod_wsgiとともに使うには?を参考に設定していきます。
 まずは/etc/httpd/conf.d/django.confを作成、内容は↓

/etc/httpd/conf.d/django.conf
WSGIScriptAlias / /home/username/django_sample/sample/mysite/wsgi.py
WSGIPythonPath /home/username/django_sample/sample:/home/username/venv/lib/python3.6/site-packages
<Directory /home/username/django_sample/sample/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

 WSGIScriptAliasの最初の/は、ルートURLの設定です。
/mysiteとかにするとhttp://123.456.789.33(仮)/mysite/ がルートURLになります。

 WSGIPythonPathでアプリのルートディレクトリ及び仮想環境のライブラリディレクトリを指定しています。

 今回はユーザーディレクトリにアプリを置いているので、/etc/httpd/conf.d/userdir.conf ファイルを編集します。
→参照:CentOS7にPython3をインストールしてDjangoを動かす

/etc/httpd/conf.d/userdir.conf
<IfModule mod_userdir.c>
    #
    # UserDir is disabled by default since it can confirm the presence
    # of a username on the system (depending on home directory
    # permissions).
    #
    UserDir enable

    #
    # To enable requests to /~user/ to serve the user's public_html
    # directory, remove the "UserDir disabled" line above, and uncomment
    # the following line instead:
    #
    #UserDir public_html
</IfModule>

 ユーザーディレクトリの権限を変更

VPS
[username@hogehoge ~]$ cd /home
[username@hogehoge home]$ sudo chmod 755 username

 httpdをリスタート

VPS
[username@hogehoge ~]$ sudo service httpd restart

 これでルートURL http://123.456.789.33(仮) 等へアクセスすると動作が確認出来る様になるかと思います。

DBへのアクセス権限

 このままではadminページへ入る際等に、DBファイルへのアクセスが出来ないというエラーが出るのでdb.sqlite3への権限を変更する必要があります。

 色々試して、結局以下の様にその他に権限を与えて何とかしていますが、あまりよろしくない様やり方かと思うので、他のやり方等ご存知の方いましたらご指摘頂けると助かります…。

VPS
[username@hogehoge ~]$ cd django_sample
[username@hogehoge django_sample]$ sudo chmod 757 sample
[username@hogehoge django_sample]$ cd sample
[username@hogehoge sample]$ sudo chmod 756 db.sqlite3
[username@hogehoge ~]$ sudo service httpd restart

staticファイルの反映

 また、adminページも含め、CSSやjavascriptが反映されていないかと思いますので、Apache等Webサーバからstaticファイルを配信する様設定する必要があります。 
 manage.py collectstaticコマンドを使って静的ファイルをSTATIC_ROOTに集め、WebサーバがSTATIC_ROOTをSTATIC_URLの場所で公開する様に設定する形になります。

  Django公式サイトのファイルを配信するを参考に設定していきます。まずはsettings.pyの編集。最下部に以下を記述。

settings.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

 次に/etc/httpd/conf.d/django.confに以下を追記。
http://123.456.789.33(仮)/static/ 等でstaticファイルにアクセス出来る様になる。

/etc/httpd/conf.d/django.conf
Alias /static/ /home/username/django_sample/sample/static/

<Directory /home/username/django_sample/sample/static>
Require all granted
</Directory>

 settings.pyのDEBUGをFalseに変更します。

settings.py
DEBUG = False

 以上の設定を行い、collectstaticコマンドを使うと、/home/django_sample/sample/static下にstaticファイルが集められ、反映されると思います。

VPS
(venv) [username@hogehoge sample]$ ./manage.py collectstatic
(venv) [username@hogehoge sample]$ sudo service httpd restart

 以上でチュートリアルのpollsアプリがstaticファイルが反映された状態で動作確認出来るかと思います。

補足:複数のアプリで共通のstaticファイルがある場合

 例えばcommon下のstaticファイルをpolls/polls2/polls3アプリで利用している場合。

sample
├── db.sqlite3
├── manage.py
├── mysite
│   ├── __init__.py
│   ...
├── polls
├── polls2
├── polls3
└── common
    └── static
        ├── css
        ├── js
        ├── images

 settings.pyに次の様にSTATICFILES_DIRSを記述します。

settings.py
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'common/static/'),
)
index.html
{% load static %}
<script src="{% static 'js/common.js' %}"></script>

の様な形で共通のstaticファイルを利用することができます。