見出し画像

VPS(Vultr)デプロイチュートリアル

自己紹介

プログラミング講師の飼鳥晴康(@hathle)です。

エンジニア歴は10年以上で海外(カナダ)就労も経験しています。

カナダでは、映画を作っていました。

現在は、独立して、Python、Djangoをメインにオンラインでマンツーマンレッスンをしています。

お問い合わせなどは、Twitter(@hathle)からお願いいたします。

プログラミングは人生を変えることができます。

目標に向かって、一緒に頑張っていきましょう!!

はじめに

VPS(Vultr)を契約してDjangoをデプロイしましょう。

VPSとは?

VPSはVirtual Private Serverの略です。

仮想専用サーバーになります。

ユーザー毎の専用領域を作成して使用します。

一からサーバーを構築するので、インフラの知識が必要になってきます。

VPSはVultrを利用します。

上記のリンクから登録すると、$100無料です。

画像19

Zenn

Zennのチュートリアルは見やすくなっています。

目標

下記を学習していきます。

・VPS契約
・サーバー構築方法
・公開方法
・ドメイン取得

前提知識

デプロイを始める前に、下記は学習しておいて下さい。

・Linuxコマンド
・インフラ
・サーバー構築

ブログ構成チュートリアルでDjangoを詳しく説明していますので、まだ実施していない方は、実施して下さい。

では、始めて行きましょう!!

Vultrサーバー構築

Vultrでサーバーを構築する準備をします。

Vultrとは?

Vultrはオーストラリアの会社が運営している格安VPSになります。

安くて高性能なので多くの人が利用しています。

Vultrの特徴

・初期費用がない
・東京リージョンがある
・コントロールパネルが使いやすい
・ファイヤーウォールの設定が可能
・料金が安い
・高性能で早い

アカウント登録

Vultrでアカウントを作成します。

Vultrを使用するには、クレジットカードを登録する必要があります。

登録しても勝手に課金されることはないので安心してください。

メールアドレスの認証もしておいてください。

sshキー作成

ローカルでsshキーを作成します。

$ ssh-keygen -t rsa

sshキーをcatコマンドで表示できるので、コピーします。

$ cat ~/.ssh/id_rsa.pub

sshキー登録

vultrにログインして、コピーしたsshキーを登録します。

画像19

画像18

ファイヤーウォール設定

ProductsのFirewall画面に遷移して、プラスボタンをクリックします。

画像19

Descriptionに適当な名前を入力します。

下記のように登録します。

・ssh:22番
・http:80番
・https:443番
・mysql:3306番

画像18

VPSレンタル

VPSをレンタルします。

ProductsのInstances画面に遷移して、プラスボタンをクリックします。

画像19

インスタンスの種類を順番に選択していきます。

・Choose Server:Cloud Compute
・Server Location:Tokyo

画像18

・Server Type:Ubuntu 18.04
・Server Size:$5

画像18

・SSH Keys:先ほど登録したsshキー
 ・Firewall Group:先ほど登録したfirewall

Deploy Nowをクリックすると、インスタンスが作成されます。

画像18

インスタンスができると、サーバーの情報を表示することができます。

IPアドレスと管理パスワードはメモしておきます。

画像19

ログイン

ローカルのターミナルから、vultrのVPSサーバーにログインできるか試してみましょう。

xxx.xxx.xxx.xxxは作成したIPアドレスになります。

$ ssh root@xxx.xxx.xxx.xxx

ユーザー作成

rootでログインできたら、ユーザーを作成します。

パスワードは表示されないので、慎重に入力してください。

英数字、記号も混じっていないとはじかれると思います。

user infomationは全部Enterを押して進行します。

・Full Name []:
・Room Number []:
・Work Phone []:
・Home Phone []:
・Other []:
root@vultr:~# adduser haruyasu

ユーザー権限変更

ユーザーにsudo権限を与えます。

root@vultr:~# gpasswd -a haruyasu sudo

ユーザーでログイン

root@vultr:~# su haruyasu

アップデート

haruyasu@vultr:~$ sudo apt update
haruyasu@vultr:~$ sudo apt upgrade
haruyasu@vultr:~$ sudo apt install nginx python3-pip python3-venv

作業用のフォルダ作成

作業用のフォルダを作成し、ここにプロジェクトをおくようにすると整理しやすくなります。

haruyasu@vultr:~$ mkdir src

VSCodeでログイン

VSCodeにRemote SSHというプラグインがあるので、ダウンロードしましょう。

画像19

Remote SSHを使用すると、VSCodeがVultrに接続できるので、フォルダが見れるようになります。

このコマンドでアクセスできます。

ssh haruyasu@xxx.xxx.xxx.xxx

画像18

デプロイ設定

デプロイに必要な設定をします。

ローカルで開発しているだけでは設定を変える必要はないですが、デプロイするとなると、セキュリティ面を考慮して設定を変更する必要があります。

.gitignore

GitHubにコミットしないように、追加します。

.gitignore

myvenv
db.sqlite3
.vscode
__pycache__
*.pyc
.DS_Store
images
media
local_settings.py
.env

requirements.txt

django-environとgunicornを追加します。

requirements.txt

Django~=2.2.10
Pillow~=2.2.1
django-widget-tweaks~=1.4.8
django-environ~=0.4.5
gunicorn~=20.0.4

settings

settingsを下記のように変更します。

本番環境ではDEBUGをFalseに設定し、envファイルからパスワードなどの重要な値を取得するようにします。

mysite/settings.py

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app',
    'widget_tweaks',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'mysite.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'mysite.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

USE_I18N = True

USE_L10N = True

USE_TZ = True

STATIC_URL = '/static/'
MEDIA_URL = '/media/'

# デプロイ設定
DEBUG = False

try:
    from .local_settings import *
except ImportError:
    pass

# ローカル用設定
if DEBUG:
    ALLOWED_HOSTS = ['*']
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

if not DEBUG:
    import environ
    env = environ.Env()
    env.read_env(os.path.join(BASE_DIR,'.env'))

    SECRET_KEY = env('SECRET_KEY')
    ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')

    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_HOST = 'smtp.gmail.com'
    EMAIL_PORT = 587
    EMAIL_HOST_USER = env('EMAIL_HOST_USER')
    EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD')
    EMAIL_USE_TLS = True

    STATIC_ROOT = '/usr/share/nginx/html/static'
    MEDIA_ROOT = '/usr/share/nginx/html/media'

コード解説

STATIC_ROOTとMEDIA_ROOTをnginxのディレクトリに設定します。

アップロードした画像は、nginxのmediaフォルダに直接アップデートされます。

STATIC_ROOT = '/usr/share/nginx/html/static'
MEDIA_ROOT = '/usr/share/nginx/html/media'

local_settings

ローカル用のsettingsファイルを用意します。

DEBUGはTrueにして、シークレットキーを追加しておきます。

mysite/local_settings.py

DEBUG = True
SECRET_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx'

urls

画像を使用する場合は、if settings.DEBUG:として判定します。

mysite/urls.py

from django.contrib import admin
from django.urls import path, include

from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

env

環境設定ファイルを用意します。

ローカルでは必要ないですが、本番環境で使用するために、準備しておきます。

ルートディレクトリに.envファイルを作成します。

.env

SECRET_KEY=xxxxxxxxxxxxxxxx
ALLOWED_HOSTS=127.0.0.1,xxx.xxx.xxx.xxx,yourdomain.com
EMAIL_HOST_USER=xxxxx@gmail.com
EMAIL_HOST_PASSWORD=xxxxxxxx

コード解説

ALLOWED_HOSTS はVultrのIPアドレスとドメインを指定します。

ALLOWED_HOSTS=127.0.0.1,xxx.xxx.xxx.xxx,yourdomain.com

デプロイ

デプロイ用の設定が完了したので、デプロイしていきます。

サーバーの構成は、クライアント → Nginx → gnicorn → djangoとなります。

画像19

クローン

アプリケーションをGitHubからクローンします。

cd
mkdir src
cd src
git clone https://github.com/xxxx/deploytest.git
cd deploytest

仮想環境構築

仮想環境を構築します。

haruyasu@vultr:~/src/deploytest$ python3 -m venv myvenv

仮想環境実行

仮想環境を実行します。

haruyasu@vultr:~/src/deploytest$ source myvenv/bin/activate

最新pipコマンド

最新にアップデートしておきます。

(myvenv) haruyasu@vultr:~/src/deploytest$ pip3 install --upgrade pip setuptools

パッケージのインストール

requirements.txtに記載されたパッケージがインストールされます。

(myvenv) haruyasu@vultr:~/src/deploytest$ pip3 install -r requirements.txt

Nginxディレクトリ作成

staticとmediaフォルダを作成します。

$ sudo mkdir /usr/share/nginx/html/static
$ sudo mkdir /usr/share/nginx/html/media

静的ファイル収集

Nginxで静的ファイルを読み込むには、下記コマンドでまとめます。

staticにあるCSSや画像を変更した場合は、必ずこのコマンドが必要になります。

このコマンドを実行するために、仮想環境ではなく直接サーバーにDjangoをインストールして下さい。

(myvenv) haruyasu@vultr:~/src/deploytest$ sudo python3 manage.py collectstatic

マイグレート

マイグレートをしておきます。

(myvenv) haruyasu@vultr:~/src/deploytest$ python3 manage.py migrate

Nginx設定

Nginxの設定を修正します。

$ sudo nano /etc/nginx/sites-available/default

デフォルトの設定を下記のように書き換えます。

Ctrl + Xで保存することができます。

server {
    listen 80;
    server_name xxx.xxx.xxx.xxx;

    location /static {
        alias /usr/share/nginx/html/static;
    }

    location /media {
        alias /usr/share/nginx/html/media;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

コード解説

server_nameはVultrのIPアドレスを指定します。

server_name xxx.xxx.xxx.xxx

HTTPS化

HTTPSに対応するには、SSL証明書を取得する必要があります。

Let's EncryptでSSL証明書を取得できます。

証明書が取得できたら、下記をHTTPS用の設定に変更する必要があります。

後で解説します。

Nginx設定確認

下記コマンドでNginxの設定が正しいかを確認することができます。

$ sudo nginx -t

Nginx再起動

$ sudo systemctl restart nginx

Nginx起動確認

nginxだけでDjangoを動作させます。

ブラウザでVultrのIPアドレスを入力して、Djangoのページが表示されることを確認します。

(myvenv) haruyasu@vultr:~/src/deploytest$ python3 manage.py runserver 0.0.0.0:8000

Gunicorn起動確認

次にGunicornを通して、Djangoを動作させます。

ブラウザでVultrのIPアドレスを入力して、このコマンドでもDjangoのページが表示されることを確認します。

(myvenv) haruyasu@vultr:~/src/deploytest$ gunicorn --bind 127.0.0.1:8000 mysite.wsgi:application

コマンド登録

起動・再起動・停止がしやすいように、systemctlコマンドへの登録をします。

deploytest.serviceなど分かりやすい名前にします。

$ sudo nano /etc/systemd/system/deploytest.service

下記のように修正します。

[Unit]
Description=gunicorn
After=network.target

[Service]
WorkingDirectory=/home/haruyasu/src/deploytest
ExecStart=/home/haruyasu/src/deploytest/myvenv/bin/gunicorn --bind 127.0.0.1:8000 mysite.wsgi:application

[Install]
WantedBy=multi-user.target

コード解説

WorkingDirectoryはDjangoプロジェクトのディレクトリです。

WorkingDirectory=/home/haruyasu/src/deploytest

gunicornの場所は仮想環境の場所になります。

which gunicornでディレクトリを表示できます。

ExecStart=/home/haruyasu/src/deploytest/myvenv/bin/gunicorn --bind 127.0.0.1:8000 mysite.wsgi:application

起動・再起動・停止

下記コマンドで容易にプロジェクトの起動停止ができます。

起動

起動コマンドは、startを使用します。

sudo systemctl start deploytest

再起動

再起動コマンドは、restartを使用します。

sudo systemctl restart deploytest

停止

停止コマンドは、stopを使用します。

sudo systemctl stop deploytest

確認

コマンドで起動したら、ブラウザでIPアドレスを入力してDjangoが表示されていることを確認しましょう。

ドメイン設定

ドメインは、お名前ドットコムで取得します。

ドメインを取得したら、ネームサーバーの設定からネームサーバーの変更を選択します。

変更するドメインを選択します。

下記のように設定します。

ネームサーバー1  ns1.vultr.com
ネームサーバー2  ns2.vultr.com

画像16

Vultr側のDNS設定

Vultr側でも設定する必要があります。

DNS画面でプラスボタンを押して、ドメイン名とIPアドレスを入力します。

画像17

画像16

環境設定変更

ALLOWED_HOSTSにドメイン名を追加します。

.env

SECRET_KEY=xxxxxxxxxxxxxxxx
ALLOWED_HOSTS=127.0.0.1,xxx.xxx.xxx.xxx,yourdomain.com
EMAIL_HOST_USER=xxxxx@gmail.com
EMAIL_HOST_PASSWORD=xxxxxxxx

サーバー再起動

サーバーを再起動させます。

sudo systemctl restart deploytest

確認

ネームサーバー変更は時間がかかります。

お名前.comからネームサーバー変更のメールが通知されるので、それまでしばらくお待ちください。

[お名前.com]ネームサーバー情報変更 完了通知

メールが届いたら、ブラウザでドメイン名を入力してページが表示されることを確認します。

もし表示されない場合は、設定を見直してください。

・サーバーが立ち上がっているか
・ファイヤーウォールは設定しているか
・ポート番号はあっているか
・httpでアクセスしているか

HTTPS化

デプロイが成功したら、HTTPS化しておきましょう。

Webアプリケーションを作成したら、HTTPS化は必須となります。

Let's Encryptをインストール

$ sudo apt-get install letsencrypt

サーバー証明書取得

Nginxを一度止めておきます。

$ sudo systemctl stop nginx

証明書を取得します。

$ sudo letsencrypt certonly --standalone -d yourdomain.com

Nginx設定

Nginxの設定をHTTPS用に修正します。

$ sudo nano /etc/nginx/sites-available/default

/etc/nginx/sites-available/default

server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com;
    return 301 https://$host$request_uri;
}


server {
    listen  443 ssl;
    server_name yourdomain.com;
    client_max_body_size 10M;

    ssl on;
    ssl_certificate         /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    location /static {
        alias /usr/share/nginx/html/static;
    }

    location /media {
        alias /usr/share/nginx/html/media;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

コード解説

yourdomain.comのところは、ドメイン名に変更して下さい。

80番ポートにアクセスがあった場合に、443ポートにリダイレクトするように設定しています。

server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com;
    return 301 https://$host$request_uri;
}

画像のアップロードサイズはデフォルトでは少ないので、最大10Mとしています。

client_max_body_size 10M;

Let's Encryptで証明書を取得すると、/etc/letsencrypt/live/に格納されます。

ssl_certificate         /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key     /etc/letsencrypt/live/yourdomain.com/privkey.pem;

collectstaticをすると、静的ファイルは/usr/share/nginx/html/staticに格納されます。

    location /static {
        alias /usr/share/nginx/html/static;
    }

画像をアップロードすると、画像は/usr/share/nginx/html/mediaに格納されます。

    location /media {
        alias /usr/share/nginx/html/media;
    }

設定確認

下記コマンドでnginxの設定が正しいことを確認します。

sudo nginx -t

Nginx開始

Nginxを開始します。

$ sudo systemctl start nginx

Gnicorn再起動

プロジェクトを再起動します。

sudo systemctl restart deploytest

確認

httpsでアプリケーションが表示されることを確認しましょう。

https://yourdomain.com

自動更新設定

証明書は90日で期限が切れてしまうので、定期的に証明書を更新します。

$ sudo crontab -e

下記を追加します。

00 05 01 ・・sudo systemctl stop nginx; sudo letsencrypt renew; sudo systemctl start nginx

VPSデプロイテクニック

初回のデプロイは設定が色々あるので、大変ですが、2回目以降は簡単です。

ローカルで開発

ローカルで開発して、動作を確認します。

GitHubにコミット

すべてのファイルをGitHubにコミットします。

VPSに接続

sshコマンドでVPSに接続します。

ssh haruyasu@xxx.xxx.xxx.xxx

フォルダ移動

gitのあるファルダに移動します。

cd src/django-portfolio

データ取得

GitHUbから最新ファイルを取得します。

git pull

静的ファイル収集

静的ファイルをnginxに集めます。

sudo python3 manage.py collectstatic

サーバー再起動

ファイルを更新したので、再起動します。

sudo systemctl restart portfolio

確認

ブラウザにURLを入力して、正常に動作していることを確認します。

以上が2回目以降の手順です。

簡単にデプロイすることができます。

おわりに

チュートリアルを最後まで読んでいただき、誠にありがとうございました。

VPSデプロイのチュートリアルはここまでで終わりとなります。

デプロイ方法

サーバー構築と本番環境へのデプロイ方法が理解できましたでしょうか!?

どんどんWebアプリケーションを開発して、全世界に公開していきましょう。

Djangoは奥の深いフレームワークで、多くの機能を搭載することができます。

公式ドキュメントを参考にして、さらに理解を深めていきましょう。

ぜひオリジナルのアプリケーションを開発してみてください。

フィードバック

チュートリアルのフィードバックは、Twitter(@hathle)までお願いいたします。

どんどんDjangoチュートリアルを作成していきますので、楽しみにしていてください。

ではまた!!

最後まで読んでいただきありがとうございました😃 サポートは、プログラミングチュートリアル開発の手助けとなります。 シェアもして頂くと嬉しいです。 Twitterのフォローもお願いします。 https://twitter.com/hathle