#日記APIを作成し、公開するところまでを初期の状態からやっていきます。
完成品はこちらです。実際に僕が日記を運用しているAPIです。笑
http://www.kojimaiton-philosophy.com/api/diaries/
日記REST_APIの使い方
CRUDで日記に必要な最低限の機能を提供します
GET
は誰でも取得可能だが、POST``PUT``DELETE
は誰からでもアクセスさせるわけにはいかないので、アクセストークンをヘッダーに付ける。
XXXXXX_XXXXXX
のところを取得したアクセストークンに置き換える。
GET
リストで日記を取得。 ページネーション、 フィルター、 リミット・オフセットも使用可能。
$ curl http://localhost/api/diaries/
日付を主キーにして、日付の日記一件を取得。
$ curl http://www.kojimaiton-philosophy.com/api/diaries/2016-12-19/
POST
日記に必要な内容を入れて、新規で作成する ※日付を主キーにしているので、同じ日付は二回POSTできない。
$ curl -X POST http://www.kojimaiton-philosophy.com/api/diaries/ -d "date=2017-03-25" -d "title=日記のタイトル" -d "body=日記の内容" -d "publishing=true" -H "Authorization: JWT XXXXXX_XXXXXX"`
PUT
更新したい日付をパスに指定して、変更したいデータに書き換えて更新する。
$ curl -X PUT http://www.kojimaiton-philosophy.com/api/diaries/2017-03-25/ -d "date=2017-03-25" -d "title=日記のタイトルの変更" -d "body=日記の変更" -d "publishing=false" -H "Authorization: JWT XXXXXX_XXXXXX"
DELETE
削除したい日付をパスに指定して、データを削除。
$ curl -X DELETE http://www.kojimaiton-philosophy.com/api/diaries/2017-03-25/ -H "Authorization: JWT XXXXXX_XXXXXX"
環境
CentOS: 7.3.1
Python: 3.6.0
Django: 1.10.6
Restframework: 3.6.2
MySQL: 5.7.17
Nginx: 1.11.13
設定
基本設定
yumをアップデート
$ sudo yum update -y
gitをインストール
$ sudo yum install git -y
必要なライブラリを入れておく
$ sudo yum install zlib-devel bzip2 bzip2-devel readline-devel openssl-devel sqlite3 sqlite-devel gcc -y
ポート関連の設定
練習のためにfirewalldを切っておく
$ systemctl stop firewalld
firewalld自動起動停止
$ systemctl disable firewalld
SELinixの確認
$ getenforce
もし Enforcingの場合は、 以下で編集しSELINUX=enforcingをSELINUX=disabledに書き換える。
$ sudo vi /etc/selinux/config
書き換えた場合は設定を反映させるためにマシンを再起動
$ sudo shutdown -r now
Disabledであることを確認する
$ getenforce
pyenvのインストール
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
$ exec $SHELL -l
確認
$ pyenv -v
pythonのインストール
バーションを確認
$ pyenv install -l
今回は 3.6.0 インストール ※インストールが終わるのにかなり時間が掛かる
$ pyenv install 3.6.0
確認
$ pyenv versions
デフォルトを変更
$ pyenv global 3.6.0
確認
$ pyenv versions
Djangoと使用するライブラリのインストール
Djangoのインストール(python3.6からはpipがデフォルトで使用可能)
$ pip install django
REST_Frame_Workのインストール
$ pip install djangorestframework
フィルタリング
$ pip install django-filter
JWTによるアクセストークン
$ pip install djangorestframework-jwt
Djangoでmysqlを塩う
$ pip install PyMySQL
Djangoを本番サーバーで実行
$ pip install uwsgi
Djangoプロジェクトの作成
プロジェクトを作成
$ django-admin startproject django_rest_framework
$ cd django_rest_framework
ホスト名を修正。自分で使っているIP・ドメインを入れる事。
$ sudo vi django_rest_framework/settings.py
ALLOWED_HOSTS = ['160.16.65.138', 'localhost', '127.0.0.1',]
manage.pyファイルがあるディレクトでサーバーを起動し、ブラウザで接続を確認する。 http://ドメイン名:8000 で確認できる。 サーバーの終了はCtrl+C
$ python manage.py runserver 0.0.0.0:8000
サーバー起動中はsettings.pyのdebugモードがデフォルトでtrueになっているので、ファイルを編集すれば、即サーバーに反映される。
DBの設定
CentOS側のDBの設定
SQLiteを使えば手軽だが、ここではしっかりと汎用的に使えるMySQLを採用します。(設定が長いですが)
先ほど、実行してできてしまったdb.sqlite3を削除する。
$ ls
db.sqlite3 diary manage.py
$ rm db.sqlite3
centos7からはmariaDBがデフォルト入っているので、削除
$ sudo yum remove mariadb-libs -y
別バージョンのmysqlを使用していた場合、そのデータが残っている可能性があるため削除
$ rm -rf /var/lib/mysql/
MySQLのリポジトリを追加
$ sudo yum -y install http://dev.mysql.com/get/mysql57-community-release-el6-7.noarch.rpm
インストール可能な内容を確認
$ yum repolist enabled | grep "mysql.*-community.*"
infoコマンドで情報を確認
$ yum info mysql-community-server
インストール
$ sudo yum -y install mysql-community-server
バージョン確認
$ mysql --version
自動起動
$ sudo chkconfig mysqld on
起動
$ sudo systemctl start mysqld
デフォルトのパスワードの確認
$ sudo vi /var/log/mysqld.log
log ファイルから以下の仮のパスワードを見つけ出す。 今回、自分のパスワードは (E,irsThV0uB のようだ
2017-04-01T20:05:05.561190Z 1 [Note] A temporary password is generated for root@localhost: N4IYvEp&)6%!
以下を実行するとパスワードを求められるので、上記で見つけ出したパスードを入力する
$ mysql -u root -p
仮パスワードを変更しないと、一切の処理を受け付けてくれないので変更する。 ただしこのパスワードは8文字以上、英字、数字、記号をそれぞれ含めないといけないと受け付けてくれないので、注意。
$ ALTER USER root@localhost IDENTIFIED BY '@Mysql0001';
設定されたら、mysqlを一旦exit
$ exit;
以下のファイルに一行加えて日本語設定をする。 [mysqld]の下に、character-set-server=utf8 を追加。
$ sudo vi /etc/my.cnf
記述はこんな感じ↓
[mysqld]
character-set-server=utf8
設定を反映
$ sudo systemctl restart mysqld
Djangoで使用するためのDBを作成する
$ mysql -u root -p
ここではdiarydbという名前にする。
$ create database diarydb;
作成したら終了
$ exit
Django側のDB設定
settings.pyを編集
$ vi django_rest_framework/settings.py
import os
# pymysqlをimportする
import pymysql
# mysqlを使用するように変更
pymysql.install_as_MySQLdb()
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
# データベース名
'NAME': 'diarydb',
# ユーザー名
'USER': 'root',
# パスワード
'PASSWORD': '@Mysql0001',
# サーバのIPアドレスやホストを。空欄はローカルホスト
'HOST': '',
# ポート
'PORT': '3306',
'OPTIONS': {
# 制約を厳しくチェック
'sql_mode': 'traditional',
},
# テスト用ユーザー
'TEST_NAME': 'auto_tests',
}
}
DjangoとMySQLが接続できるか確認
migrationファイルを作る
$ python manage.py makemigrations
migrationファイルを元にDBに反映する
$ python manage.py migrate
DBの設定が終了...長い
Djangoプロジェクトを編集
日記appを作成
$ cd django_rest_framework
$ python manage.py startapp diary
現状のディレクトリ構成はコチラ。大枠ここに少しづつファイルを足す感じです
└── django_rest_framework
├── diary
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── django_rest_framework
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ ├── settings.cpython-36.pyc
│ │ ├── urls.cpython-36.pyc
│ │ └── wsgi.cpython-36.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
モデルを定義
モデルはDBと一対一になる。
models.py を作成
$ vi diary/models.py
# coding: utf-8
from django.db import models
from datetime import date
class Diary(models.Model):
date = models.DateField(default=date.today, primary_key=True)
title = models.CharField(max_length=128)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
publishing = models.BooleanField(default=True)
作成した model
を settings.py
に定義
$ vi django_rest_framework/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# diaryを追加
'diary',
]
もう一度DBをマイグレーション
$ python manage.py makemigrations
$ python manage.py migrate
DjangoのDBの管理画面に入る
admin用のユーザー作成
$ python manage.py createsuperuser
サーバーを起動。
$ python manage.py runserver 0.0.0.0:8000
管理画面にアクセス http://自分のIP・ドメイン:8000/admin/
先ほど createsuperuser
で作成した Username
と Password
を入力して管理画面に入る。
GUIをポチポチして、モデルを編集したり、追加したりできます。
ここに先ほど作成したモデルもGUIから操作できるように加えます。
$ vi diary/admin.py
# coding: utf-8
from django.contrib import admin
from .models import Diary
@admin.register(Diary)
class Diary(admin.ModelAdmin):
pass
管理画面に DIARY
が加わっています
APIで使用するために、ここで日記をいくつか作って置きましょう。
Diarys -> Add diary -> SAVE
REST frameworkの導入
REST frameworkを定義
$ vi django_rest_framework/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# diaryを追加
'diary',
# frameworkを追加
'rest_framework',
]
Serializerを定義
APIへの出力対象のフィールドは Serializerクラス内で制限する
$ vi diary/serializer.py
# coding: utf-8
from rest_framework import serializers
from .models import Diary
class DiarySerializer(serializers.ModelSerializer):
class Meta:
model = Diary
fields = ('date', 'title', 'body', 'publishing',)
ViewSetを定義
ViewSetはコントローラー
$ vi diary/views.py
# coding: utf-8
from rest_framework import viewsets
from .models import Diary
from .serializer import DiarySerializer
class DiaryViewSet(viewsets.ModelViewSet):
queryset = Diary.objects.all()
serializer_class = DiarySerializer
Urlsを定義
UrlsはURLのルーター設定
作成したDiaryViewSet
を登録する
$ vi diary/urls.py
# coding: utf-8
from rest_framework import routers
from .views import DiaryViewSet
router = routers.DefaultRouter()
router.register(r'diaries', DiaryViewSet)
外部からアクセスされるルーティーングの設定
$ vi django_rest_framework/urls.py
# coding: utf-8
from django.conf.urls import url, include
from django.contrib import admin
from diary.urls import router as diary_router
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include(diary_router.urls)),
]
実行して確認してみる
サーバーを立ち上げる
$ python manage.py runserver 0.0.0.0:8000
ブラウザで接続
http://自分のIP・ドメイン:8000/api/diaries/
curlで叩くと、json
が返ってきている。
$ curl http://160.16.65.138:8000/api/diaries/
[{"date":"2017-04-15","title":"タイトルテスト","body":"中身テスト","publishing":true},{"date":"2017-04-16","title":"タイトル","body":"中身!","publishing":true}]
ここで注意点ですが、上記の写真のGET
横のボタンでプルダウンからjsonで見ると文字化けします。
Chromeのバージョンによっては文字化けしてないかもしれませんが、それは自動でUTF-8
に変換してくれているからです。
SafariなどでUTF-8
指定をしないまま見ると、文字化けしていると思います。
下記を直すにはクライアントに返すjson
にUTF-8
をこちらで指定しなければいけません。
jsonをutf-8指定にする
REST Framework
のドキュメントにはデフォルトでUTF-8と書いてあるが
$ vi diary/renderers.py
UTF-8
を指定したUTF8CharsetJSONRenderer
クラスの作成
デフォルトのrest_framework.renderers.JSONRenderer
でUTF-8
になっていそうだが、出来なかった。。。
from rest_framework.renderers import JSONRenderer
class UTF8CharsetJSONRenderer(JSONRenderer):
charset = 'utf-8'
settings.py
に以下を追記
$ vi django_rest_framework/settings.py
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'diary.renderers.UTF8CharsetJSONRenderer',
)
}
文字化けが直った
CURDの確認
IPの所は自分のに変更してリクエストする事
POST(Create)
新規作成
$ curl -X POST http://160.16.65.138:8000/api/diaries/ -d "date=2017-04-22" -d "title=日記のタイトル" -d "body=POSTのテスト" -d "publishing=true"
PUT(Update)
更新
$ curl -X PUT http://160.16.65.138:8000/api/diaries/2017-04-22/ -d "date=2017-04-22" -d "title=日記のタイトルの変更" -d "body=PUTのテスト" -d "publishing=false"
GET(Read)
リストの取得
$ curl http://160.16.65.138:8000/api/diaries/
日付で取得
$ curl http://160.16.65.138:8000/api/diaries/2017-04-22/
DELETE(Delete)
削除
$ curl -X DELETE http://160.16.65.138:8000/api/diaries/2017-04-22/
ページネーション
ページネーションを追加
$ vi django_rest_framework/settings.py
REST_FRAMEWORK = {
# 追加
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 3,
'DEFAULT_RENDERER_CLASSES': (
'diary.renderers.UTF8CharsetJSONRenderer',
)
}
取得するとjsonのルートにnext
とprevious
が追加され、前後のページを辿れる。
$ curl http://160.16.65.138:8000/api/diaries/
{
count: 4,
next: "http://160.16.65.138:8000/api/diaries/?limit=3&offset=3",
previous: null,
results: [
{
date: "2017-04-15",
title: "タイトルテスト",
body: "中身テスト",
publishing: true
},
{
date: "2017-04-16",
title: "タイトル",
body: "中身!",
publishing: true
},
{
date: "2017-04-21",
title: "hoge",
body: "ssss",
publishing: true
}
]
}
フィルター
views.py
を編集
$ vi diary/views.py
# coding: utf-8
from rest_framework import viewsets
from .models import Diary
from .serializer import DiarySerializer
class DiaryViewSet(viewsets.ModelViewSet):
queryset = Diary.objects.all()
serializer_class = DiarySerializer
# フィルタを追加
filter_fields = ('publishing',)
settings.py
を編集
$ vi django_rest_framework/settings.py
REST_FRAMEWORK = {
# フィルター追加
'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',),
# ページネーション追加
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 3,
'DEFAULT_RENDERER_CLASSES': (
'diary.renderers.UTF8CharsetJSONRenderer',
)
}
公開フラグをfalse
のものだけフィルタしてみる ?publing=false
をリクエストに付ける
$ curl http://160.16.65.138:8000/api/diaries/?publing=false
{
count: 1,
next: null,
previous: null,
results: [
{
date: "2017-04-22",
title: "hogehoge",
body: "hoge",
publishing: false
}
]
}
認証
認証方法は色々あるが今回はJWT(Json Web Token)を使用
settings.py
を編集
$ vi django_rest_framework/settings.py
REST_FRAMEWORK = {
# JWTの認証追加
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
'NON_FIELD_ERRORS_KEY': 'detail',
'TEST_REQUEST_DEFAULT_FORMAT': 'json',
# フィルター追加
'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',),
# ページネーション追加
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 3,
'DEFAULT_RENDERER_CLASSES': (
'diary.renderers.UTF8CharsetJSONRenderer',
)
}
# JWTの認証追加
JWT_AUTH = {
# トークンの期限をここでは無効にしてみる
'JWT_VERIFY_EXPIRATION': False,
}
urls.py
を編集
$ vi django_rest_framework/urls.py
# coding: utf-8
from django.conf.urls import url, include
from django.contrib import admin
from diary.urls import router as diary_router
# 認証を追加
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include(diary_router.urls)),
# 認証を追加
url(r'^api-auth/', obtain_jwt_token),
]
JWTのアクセストークンの取得
createsuperuser
で作成したadmin
ユーザーのusername
とpassword
を入れてリクエスト
$ curl http://160.16.65.138:8000/api-auth/ -d "username=XXXXXXX&password=XXXXXXXX"
成功した場合レスポンスにtoken
が入ってくる。
{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJlbWFpbCI6Im11dS5rb2ppbWEudGVzdEBnbWFpbC5jb20iLCJ1c2VybmFtZSI6ImRqYW5nbyIsImV4cCI6MTQ5Mjg1NTMxMH0.m07BcTiAkA79HZ0BC8BsgYOA-SbqmC5GMN5g_QBizZw"}
ユーザー名やパスワードが違うと以下のように失敗する
{"detail":["Unable to login with provided credentials."]}
views.py
を編集し、認証を掛ける
$ vi diary/views.py
# coding: utf-8
from rest_framework import viewsets
from .models import Diary
from .serializer import DiarySerializer
# 認証追加
from rest_framework import permissions
class DiaryViewSet(viewsets.ModelViewSet):
queryset = Diary.objects.all()
serializer_class = DiarySerializer
# フィルタを追加
filter_fields = ('publishing',)
# 認証追加 CURD全てに認証掛けたい場合は (permissions.IsAuthenticated,)にする
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
認証が掛かっているか試す
新規作成
$ curl -X POST http://160.16.65.138:8000/api/diaries/ -d "date=2017-04-21" -d "title=認証" -d "body=認証のテスト" -d "publishing=true"
アクセストークンがないので以下のように失敗すればOK!
{"detail":"Authentication credentials were not provided."}
取得したアクセストークンを付けてPOSTする ※アクセストークンは自分のに変えること
$ curl -X POST http://160.16.65.138:8000/api/diaries/ -d "date=2017-04-10" -d "title=認証" -d "body=認証のテスト" -d "publishing=true" -H "Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJlbWFpbCI6Im11dS5rb2ppbWEudGVzdEBnbWFpbC5jb20iLCJ1c2VybmFtZSI6ImRqYW5nbyIsImV4cCI6MTQ5Mjg1NTMxMH0.m07BcTiAkA79HZ0BC8BsgYOA-SbqmC5GMN5g_QBizZw"
作成できたら、GET
以外全てに認証が掛かっているかを確認する
※ 参考permissions.IsAuthenticatedOrReadOnly
なので、 OrReadOnly
を取れば、GET
にも認証が掛かる。
404ページを通常のに修正。
現状ルートにアクセスすると、Djangoのデフォルトでは以下のようになる
http://160.16.65.138:8000/
下の方の文言通りに、 settings.py
を編集し、DEBUG = False
に設定する ※ DEBUG = False
にするとサーバーを起動しながら、自動でファイルの変更を反映する事ができないので注意
You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
$ vi django_rest_framework/settings.py
...省略
# DEBUG = Falseにすると通常の404ページになる
DEBUG = False
...省略
アクセスすると通常の404ページになった!
テストケース
tests.pyを削除
$ rm diary/tests.py
テスト用ディレクトリ作成。ここにテストを入れる
$ mkdir diary/tests
pythonのディレクトリと認識されるように`__init__.py` を追加。 特に何も記述はしない。
$ vi diary/tests/__init__.py
認証とCRUDのテストをするための test_diary.py
を作成
$ vi diary/tests/test_diary.py
# coding: utf-8
from rest_framework import status
from rest_framework.test import APITestCase
from rest_framework_jwt.compat import get_user_model
from rest_framework_jwt.settings import api_settings
class DiaryTest(APITestCase):
def setUp(self):
# アクセストークンの発行
User = get_user_model()
self.username = 'test_user'
self.email = 'test_user@gmail.com'
self.user = User.objects.create_user(self.username, self.email)
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(self.user)
token = jwt_encode_handler(payload)
self.auth = 'JWT {0}'.format(token)
self.url = '/api/diaries/'
def test_diary_api(self):
# POST
data = {
"date": "2011-11-11",
"title": "title",
"body": "body",
"publishing": True,
}
response = self.client.post(self.url, data, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data, data)
# GET
expected_get_data = {
"count": 1,
"next": None,
"previous": None,
"results": [
{
"date": "2011-11-11",
"title": "title",
"body": "body",
"publishing": True,
}
]
}
response = self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, expected_get_data)
# PUT
data2 = {
"date": "2010-10-10",
"title": "title",
"body": "body",
"publishing": False,
}
response = self.client.put(self.url + '2011-11-11/', data2, HTTP_AUTHORIZATION=self.auth)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, data2)
# DELETE
response = self.client.delete(self.url + '2010-10-10/', HTTP_AUTHORIZATION=self.auth)
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
テストを実行
以下を実行すると、 tests
の中の test_xxxx.pyが実行される。
$ ./manage.py test
テストが通った!
[xxxxx@tk2-208-13884 django_rest_framework]$ ./manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.049s
OK
Destroying test database for alias 'default'...
リバースプロキシの設定(APIのエンドポイントの:8000を消す)
nginxのインストール
リポジトリを追加するので nginx.repo
のファイルを作成
$ sudo vi /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1
インストールと起動
nginxをインストール
$ sudo yum install nginx -y
バージョンの確認
$ nginx -v
自動起動設定
$ sudo systemctl enable nginx
起動
$ sudo systemctl start nginx
デフォルトページの確認
表示の確認をする。 http://自分のサーバーのIP/
以下は自分の例。
http://160.16.65.138/
※上記の index.html
のデフォルトのパスは /usr/share/nginx/html/index.html
リバースプロキシを設定する
/etc/nginx/conf.d 以下に XXX.confという命名でファイルを作成する
ココでは server.conf とし、80 番で受けたリクエストを 8000 番に転送する
$ sudo vi /etc/nginx/conf.d/server.conf
server {
listen 80;
# アクセス可能なIPアドレス、もしくはドメイン。以下は自分の例
server_name 160.16.65.138;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_max_temp_file_size 0;
location / {
# 転送先
proxy_pass http://localhost:8000;
}:joy:
}
nginx再起動させ設定を反映させる
$ sudo systemctl restart nginx
実行すると、ブラウザからはデフォルトHTTPの80
でアクセスできる用になるので、 8000
が不要になる
python manage.py runserver 0.0.0.0:8000
Djangoをデーモンで起動し、本番環境で実行する
サーバーからexit
してもバックグラウンドで動き続けるようにしてみる。
ルートにパスワードを設定
$ sudo passwd root
ルートになる
$ su
本番環境のデーモンでDjangoを実行
$ uwsgi --http :8000 --module django_rest_framework.wsgi --daemonize /var/log/uwsgi-django.log
以上で、バックグラウンドで動いているはず!
バックグラウンドで動いているuwsgi
の止め方は動かしてるサーバーのPID
をkill
する。
調べる
$ netstat -ntlp
uwsgi
の横に表示されているが、PID
なので、
この場合は kill -9 32215
でサーバーが停止する
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 32181/nginx: master
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 861/sshd
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 32215/uwsgi
tcp 0 0 127.0.0.1:43047 0.0.0.0:* LISTEN 32215/uwsgi
tcp6 0 0 :::22 :::* LISTEN 861/sshd
tcp6 0 0 :::3306 :::* LISTEN 19382/mysqld
uwsgi
の読み方はウィスキーらしい?
"上杉"と読んでいた
## まとめ
Githubに完成品をあげて置きます
実際に僕が日記を運用しているAPIです。笑
http://www.kojimaiton-philosophy.com/api/diaries/
拡張しつつ、生涯掛けて運用していきます
こちらはAWSで運用しています!
参考
http://qiita.com/redamoon/items/eabaacabb5b1a0c34ca3
http://qiita.com/seizans/items/05a909960820dd92a80a
http://racchai.hatenablog.com/entry/2016/05/08/070000
http://var.blog.jp/archives/70125676.html