Django + Nginx + Gunicorn でアプリケーションを立ち上げる

サーバー基本構築

Django アプリケーションを立ち上げるにあたりまず、サーバーの基本的な設定を実施していきます。ただし、サーバーの契約等は全て終わっているものとして進めます。

完成目標

下記環境で動作するブログサイトを構築する。サーバーは、さくらのVPSを使用しました。

項目 バージョン
CentOS 7.2
Python 3.6
Django 1.11.6
Gunicorn 19.7.1
Nginx 1.13.9
MySQL 5.7

ユーザー周りの設定

  1. サーバーに root でログインします。
  2. ユーザーを追加します。
    # useradd <追加したいユーザー名>
  3. 追加したユーザーのパスワードを設定します。
    # passwd <追加したユーザー名>
  4. 追加したユーザーの sudo の設定をします。
    CentOS にはデフォルトで wheel グループという sudo 可能なグループが存在するので追加したユーザーを wheel グループに所属させることで sudo 可能にします。
    visudo コマンドを使用して etc/sudoers ファイルを開き、下記行がコメントアウトされている場合は有効にします。
    # visudo
    99 %wheel  ALL=(ALL)       ALL
  5. 追加したユーザーを wheel グループに所属させます。
    # usermod -G wheel <追加したユーザー名>

公開鍵の設定

サーバーは公開鍵認証にしたいので、その設定をしていきます。公開鍵は事前にローカルマシンで作成しておいてください。作成方法は Qiita とかで検索するといっぱい投稿されているのでそちらを参照すれば作成出来ると思います。

  1. 作成したユーザーでログインします。
  2. ログイン後、デフォルトで /home/<追加したユーザー名> にいると思うので、そこに設定用のディレクトリを作成します。
    $ mkdir .ssh
    $ chmod 700 .ssh ← 適切なパーミッションに変更する。
  3. 公開鍵を設定するファイルを作成します。
    $ cd .ssh/
    $ vi authorized_keys ← 事前に作成した公開鍵を貼り付ける。
    $ chmod 600 authorized_keys ← 適切なパーミッションに変更する。

SSHの設定

これから実施する設定を反映後、設定したターミナルを閉じる前に必ず別のターミナルで ssh ログインが出来るかどうか確認してから閉じること! 仮に、設定が間違っていてログイン出来なかった場合、二度とサーバーに入れなくなり、サーバーを初期化するしかなくなってしまいます。

  1. 作成したユーザーでログインします。
  2. SSHの設定ファイルを念のためコピーをとります。
    $ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.20180627
  3. SSHの設定ファイルを編集します。
    このあたりの設定はあまり詳しくないので、下記サイト等を参考に設定しました。
    CentOS 7(さくらのVPS)サーバ作成直後に設定しておくべき初期セキュリティ設定
    sshd_configの設定内容 
    $ sudo vi /etc/ssh/sshd_config
    17 Port <設定したいポート番号>  # sshdが使うポートをウェルノウンポート以外に設定
    23 Protocol 2                 # プロトコルバージョン2を使用
    48 LoginGraceTime 20          # 認証できる制限時間を20秒以内に設定
    49 PermitRootLogin no         # Rootログインを禁止
    51 MaxAuthTries 2             # 認証にトライできる回数を2にする
    52 MaxSessions 1              # 同時可能接続数を1にする
    54 RSAAuthentication yes      # RSA認証を許可する
    55 PubkeyAuthentication yes   # 公開鍵認証を許可する
    67 RhostsRSAAuthentication no # RHostsでの認証を許可しない
    74 IgnoreRhosts yes           # ~/.rhosts ~/.shostsを無視する
    78 PermitEmptyPasswords no    # パスワードを設定していないユーザーの認証を禁止
    79 PasswordAuthentication no  # パスワード認証を禁止
    ※ SSH のポート番号をデフォルトの22から変更した場合、firewalld の設定ファイルを変更しないと SSH ログイン出来なくなります。
    $ sudo vi /usr/lib/firewalld/services/ssh.xml
    5   <port protocol="tcp" port="<変更したポート番号>"/>
    $ sudo firewall-cmd --reload
目次へ戻る

サーバー環境構築

Django アプリケーションが動作する環境を構築していきます。

Gitのインストール

デフォルトで git がインストールされている場合はそのまま使用しても差し支えないと思いますが、既存のものはバージョンが古いので、最新バージョンを入れたい人は下記手順にてインストールします。

  1. 追加したユーザーでログインします。
  2. デフォルトの git が存在する場合は、アンインストールします。
    $ sudo yum -y remove git
  3. 必要な関連ライブラリをインストールします。
    $ sudo yum -y install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker
  4. 最新版(作業当時は2.16.2)の git をダウンロードして解凍します。
    $ cd /etc/yum.repos.d/
    $ sudo wget https://www.kernel.org/pub/software/scm/git/git-2.16.2.tar.gz
    $ sudo tar xzvf git-2.16.2.tar.gz
  5. git をコンパイルしてインストールします。
    $ cd git-2.16.2/
    $ sudo make prefix=/usr/local all
    $ sudo make prefix=/usr/local install
    $ git --version
    git version 2.16.2
    $ sudo rm -f git-2.16.2.tar.gz ← 不要なので削除。
    $ sudo rm -rf git-2.16.2/ ← 不要なので削除。

Pythonのインストール

Python 3.x は CentOS 7 の標準 yum リポジトリでは提供されていないので、IUS Community Project の yum リポジトリから取得します。このリポジトリは、Red Hat Enterprise Linux(RHEL)や CentOS 向けに、できる限り最新のソフトウェアの RPM を提供することを目的としたプロジェクトで、最新の Python を yum でインストールできるようになります。

以下サイトを参考にしながら作業しました。
Python 3 を CentOS 7 に yum でインストールする手順
Python3.6インストール yum

  1. IUS Community Project のリポジトリを追加します。
    $ sudo yum install -y https://centos7.iuscommunity.org/ius-release.rpm
  2. Python と関連ライブラリをインストールします。
    Python コマンドを使用する時に毎回バージョンまで入力するのはめんどくさいので、シンボリックリンクを貼って python3 で実行できるようにします。
    python ではなく python3 にする理由は参考サイトで解説していましたが、python コマンドはデフォルトでインストールされている python 2.x にリンクされているので、区別するためにも、今回は python3 とします。
    $ sudo yum install -y python36u python36u-libs python36u-devel python36u-pip
    $ python3.6 --version
    Python 3.6.4
    $ sudo ln -s /usr/bin/python3.6 /usr/bin/python3
    $ python3 --version
    Python 3.6.4
  3. Pip コマンドもバージョンを省略して使用できるようにシンボリックリンクを作成します。
    $ sudo ln -s /usr/bin/pip3.6 /usr/bin/pip
    $ pip --version
    pip 9.0.1 from /usr/lib/python3.6/site-packages (python 3.6)

Nginxのインストールと設定

Nginx には Mainline version(最新版) と Stable version(安定版) の2種類あり、基本的には最新版の使用を開発者は推奨していますが、サードパーティモジュールとの互換性が気になる場合や、新機能のリリースで発生したバグを回避したい場合は安定版を使うとよいとのこと。今回は最新版をインストールします。

以下サイトを参考にしながら作業しました。
どのバージョンのnginxを使うべきか?
CentOS 7 (5, 6) で "安定版 (最新版)" のNginxをインストールする方法

  1. yum リポジトリを追加して、Nginx のパッケージをアップデートします。
    $ sudo rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
    $ sudo yum update nginx-release-centos
  2. 最新版を参照するように設定ファイルを変更します。
    $ sudo vi /etc/yum.repos.d/nginx.repo
    5 baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
  3. Nginx の最新版をインストールします。
    $ sudo yum -y --enablerepo=nginx install nginx
    $ nginx -v
    nginx version: nginx/1.13.9

Nginx をインストールした後は、設定をしていきます。下記サイトを参考にしながら作業しました。
Nginx設定のまとめ
nginxについてまとめ(設定編)

Nginx の設定ファイルは /etc/nginx/nginx.conf と /etc/nginx/conf.d/ 配下にあります。このあたりの設定についてはあまり詳しくないので、あくまで参考としてですが下記のように設定しました。

/etc/nginx/nginx.conf

/etc/nginx/conf.d/default.conf

MySQLのインストールと設定

下記サイトを参考にしながら作業しました。
CentOS7.1にMySQL 5.7をインストール

  1. yum リポジトリを追加します。
    $ sudo rpm -ivh https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
  2. MySQL 関連パッケージが enabled になっているかどうかを確認します。
    $ sudo yum repolist all | grep mysql | grep enabled
    mysql-connectors-community/x86_64                    MySQL Co enabled:        45
    mysql-tools-community/x86_64                         MySQL To enabled:        59
    mysql57-community/x86_64                             MySQL 5. enabled:       247
  3. MySQLをインストールします。
    $ sudo yum -y install mysql-community-server

MySQL をインストールした後は、セキュリティや DB の設定をしていきます。

  1. MySQL を起動します。
    $ sudo systemctl start mysqld
  2. サーバー起動時に MySQL を起動する設定をします。
    $ sudo systemctl enable mysqld
  3. root の初期パスワードをログから取得します。
    MySQL 5.7では、初回起動と同時にテンポラリの初期パスワードが生成されるため、MySQL のログファイルから初期パスワードを確認する必要があります。
    $ cat /var/log/mysqld.log | grep 'temporary password'
    2018-03-12T08:41:10.977905Z 1 [Note] A temporary password is generated for root@localhost: <初期パスワード>
  4. mysql_secure_installation コマンドを使用して、MySQL のセキュリティの設定をします。
    基本的に YES で問題ないかと思います。
    $ sudo mysql_secure_installation
    Enter password for user root: # ログから取得した初期パスワードを入力する。
    New password: # 新しい root のパスワードを入力する。
    
    # 下記エラーが出る場合は、validate_password_policy の初期値(MEDIUM ポリシー)を満たしていない。
    # MEDIUM ポリシーとは、パスワードが最低1つの数値、小文字および大文字、特殊文字(英数字以外)を含む必要があるというルールのこと。
    Re-enter new password:
     ... Failed! Error: Your password does not satisfy the current policy requirements
    
    # root パスワードを変更するかどうか。
    Change the password for root ? ((Press y|Y for Yes, any other key for No) : y
    New password: # 新しい root のパスワードを入力する。
    Re-enter new password: # 再度入力する。
    
    # 提供されたパスワードの利用を続けるかどうか。
    Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
    
    # 匿名ユーザーアカウントを削除するかどうか。
    Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
    
    # ローカルホスト以外からアクセス可能な root アカウントを削除するかどうか。
    Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
    
    # test データベースを削除するかどうか。
    Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
    
    # 変更を反映するかどうか。
    eload privilege tables now? (Press y|Y for Yes, any other key for No) : y
  5. パスワードの有効期限を無効にします。
    MySQL 5.7 からユーザーパスワードの有効期限が360日となっているので、これを無効にします。もちろん必ず無効にする必要はないですが、忘れた頃に有効期限が切れて突然サイトが死ぬと困るので設定しておきます。
    $ sudo vi /etc/my.cnf
    29 character-set-server = utf8 ← これはついでに設定。
    30 default_password_lifetime = 0
  6. root で MySQL にログインします。
    $ mysql -u root -p
  7. DB の設定をします。
    # DB を作成します。
    mysql> create database <DB名> character set utf8mb4;
    Query OK, 1 row affected (0.00 sec)
    
    # ユーザーを追加します。
    mysql> create user '<ユーザー名>'@'localhost' identified by '<ユーザーのパスワード>';
    Query OK, 0 rows affected (0.00 sec)
    
    # 追加したユーザーに権限を付与します。
    mysql> grant all privileges on <作成したDB名>.* to '<追加したユーザー名>'@'localhost';
    Query OK, 0 rows affected (0.00 sec)
    
    # 設定を反映します。
    mysql> flush privileges;
    Query OK, 0 rows affected (0.00 sec)

Django アプリケーションの設定

Django で作成したアプリケーションが GitHub とか GitLab にリポジトリがあることが前提で進めます。

  1. 作成したユーザーでログインします。
  2. Django アプリケーションを設置する場所へ移動します。
    どこに設定するのかに決まりはないです。僕の所属する会社では /opt がデファクトとされているのでそこに設置します。
    $ cd /opt
    $ sudo mkdir <適当なディレクトリ名>
    $ sudo chown <追加したユーザー名>:<追加したグループ名> <作成したディレクトリ名>/
    $ cd <作成したディレクトリ名>/
  3. git clone します。
    $ git clone <Github や GitLab の URL>
  4. Django アプリケーションの動作に必要なライブラリをインストールする。
    Django アプリケーション開発時に、requirements.txt のようなファイルに必要なライブラリ情報を纏めていると思いますのでそれをインストールします。
    $ pip install --user -r <requirementsファイルパス>
    $ sudo yum update # 僕はpip関連のエラーが出たので、このタイミングでyumを更新しました。
  5. マイグレーションを実行します。
    $ cd <設置したDjangoアプリケーションのmanage.pyファイルがある場所>
    $ python3 ./manage.py migrate

Gunicornの設定

Django アプリケーションを動かすための WEB サーバーとして Gunicorn を使用するのでその設定をします。また、プロセスは systemd で管理します。 個人的にここ関連の設定が一番理解出来ていないので、意味不明な設定となっていたらごめんなさい。

  1. Gunicorn の設定ファイルを作成します。
    作成場所は Django アプリケーション内に作成しました。
  2. systemd で管理するために必要な設定ファイルを作成します。
    $ cd /etc/systemd/system
    $ sudo vi <適当な名前をつけます>.service

    /etc/systemd/system/<作成した設定ファイル名>.service

  3. サービスの立ち上げと自動起動設定をします。
    $ sudo systemctl start <作成した設定ファイル名>.service
    $ sudo systemctl enable <作成した設定ファイル名>.service

Nginx と Gunicorn が正常に動いていれば、この段階で Django アプリケーションをブラウザで表示出来るようになるはずですが、表示されない場合はなにかしらの設定が足りていないかも知れません。主要な設定は全て網羅したつもりなので、後は表示されるまで調整を頑張りましょう!

目次へ戻る

終わりに

だーっとやったことを作業メモと記憶を頼りに書き綴りましたが、なんとか立ち上げることが出来た感が拭えないです。あまり理解していない箇所を端折ったり、詳しい説明が出来なかったり、不完全な記事となりましたが部分部分でも誰かの参考になれば幸いです。自分自身まだまだ勉強中の身なので、今後も復習と勉強のため不定期に色々と記事投稿を頑張っていきます!

立ち上げた WEB カーテンコールは、これからデザインや、機能等色々と手を加えていくつもりなので、ちょこちょこ見にきてもらえると何か変化があるかもしれません。これから WEB カーテンコールをよろしくお願いします!

目次へ戻る