LoginSignup
25
28

More than 3 years have passed since last update.

Django + Heroku + WhiteNoise + AWS S3 によるWebアプリのデプロイ

Last updated at Posted at 2018-12-05

はじめに

Djangoで作成したWebアプリをHerokuにデプロイする方法や、静的ファイルをWhiteNoiseで管理する方法、画像ストレージをAWSと対応させる方法などをそれぞれ断片的に解説した記事はありますが、一連の流れをまとめた記事があまり無かったため、本記事でまとめて解説しようと思います。

要旨

本記事では、Djangoで作成したWebアプリにおいて、静的ファイルをWhiteNoiseで管理し、画像や動画などのメディアファイルはAWS S3で管理して、最後にHerokuでデプロイするまでの流れを解説します。

準備

  1. Djangoを用いたWebアプリを作成
  2. AWSのアカウント作成
  3. Herokuのアカウント作成

Webアプリの開発環境

環境

Python == 3.6.7
Django == 1.11.15

サンプルアプリ

以下のようなアプリ構成で進めていきます。

sample
    ├──Procfile
    ├── blog
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   │   ├── __init__.py
    │   │   └── 0001_initial.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    ├── manage.py
    ├── requirements.txt
    ├── config
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── runtime.txt
    ├── templates
    ├── static            
    └── myvenv

ただし、myvenvはvirtualenv(仮想環境)です。
また、マイグレーションファイルは作成済みとします。(python manage.py makemigrations)

最初に、以下のコマンドで仮想環境を起動しておきます。

$ source myvenv/bin/activate

各種設定

まずは、必要なパッケージをインストールします。

(myvenv)$ pip install gunicorn 
(myvenv)$ pip install dj-database-url
(myvenv)$ pip install psycopg2
(myvenv)$ pip install psycopg2-binary

Prockfileには以下のように、wsgi.pyが保存されている場所を指定します。

Procfile
web: gunicorn config.wsgi

続いて、runtime.txtには以下のように記述します。(heroku上で動かすpythonのバージョンを指定)
Pythonの最新版を指定しないと、herokuから警告が出ます。

runtime.txt
python-3.6.7

続いては、wsgi.pyの編集です。
初期状態では、該当部分が"プロジェクト名".settingsとなっていますが、今回はconfigの下にsettings.pyがあるため、下記のように変更します。

wsgi.py
import os
from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") #変更

application = get_wsgi_application()

HerokuではSQLiteが動作しないため、setting.pyに以下のコードを追加します。

settings.py
import dj_database_url
db_from_env = dj_database_url.config()
DATABASES['default'].update(db_from_env)
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

DEBUG = False
ALLOWED_HOSTS = ['*']

静的ファイル

静的ファイルを管理するために、WhiteNoiseをインストールします。

(myvenv)$ pip install whitenoise

続いては、settings.pyを編集していきます。
MIDDLEWAREにwhitenoise.middleware.WhiteNoiseMiddlewareを追加します。

settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware', #追加
    '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',
]

さらにsettings.pyに以下のコードを追加します。

settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
STATIC_ROOT = os.path.join(BASE_DIR, 'static_root')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

最後に以下のコマンドを実行します。
すると、static_rootというフォルダが生成されます。
静的ファイルの準備はこれで完了です。

(myvenv)$ python manage.py collectstatic

メディアファイル

AWSの各種設定

メディアファイルをAWS S3で管理するには、AWSのアカウント作成、AWS側での各種設定を行っておく必要があります。
今回の目的であるメディアファイルの管理でのAWS側の設定は下記の記事がわかりやすいです。
Django、静的ファイル、メディアファイルをAWS S3で管理
上記の記事では、静的ファイルとメディアファイルを共に、AWS S3で管理していますが、今回は静的ファイルはWhite Noiseで管理するため、メディアファイルのみをAWS S3で管理します。
また、AWS側の設定に関しては、以下の記事も参考になると思います。
[Django] ファイルアップロード機能の使い方 [クラウドストレージ編]

パッケージ,コードの追加

AWS側の設定を終えたら、必要なパッケージをインストールします。

(myvenv)$ pip install django-storages
(myvenv)$ pip install boto3

続いて、settings.pyのINSTALLED_APPS'stoages'を追加します。

settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
    'storages', #追加
    ]

さらに、settings.pyに以下のコードを追加します。
アクセスキーなどはAWS側の設定の時に取得できます。
AWS_LOCATIONでメディアファイルの保存先も指定します。

settings.py
AWS_ACCESS_KEY_ID = 'アクセスキー'
AWS_SECRET_ACCESS_KEY = 'シークレットアクセスキー'
AWS_STORAGE_BUCKET_NAME = '<作成したバケットの名前>'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400', 
}

AWS_LOCATION = 'media'
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
MEDIA_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)

これで、Webアプリでアップロードされたメディアファイルは、AWS S3の作成したバケットの中のmedia/に格納されていきます。

Herokuへデプロイ

下記のコマンドによりheroku toolbeltをインストールして、herokuのコマンドを打てるようにします。

brew install heroku/brew/heroic

続いて、これまでインストールしたパッケージをrequirements.txtに書き込みます。

(myvenv)$ pip freeze > requirements.txt

次に、以下のgitコマンドを入力して、これまで作成したファイルをコミットしていきます。

(myvenv)$ git init           
(myvenv)$ git add -A .
(myvenv)$ git commit -m 'first commit'                            

最後に、以下のherokuコマンドを順に打ち込んでいきます。
heroku openで作成したアプリが開けたら、無事成功です。

(myvenv)$ heroku login
(myvenv)$ heroku create
(myvenv)$ heroku config:set DISABLE_COLLECTSTATIC=1
(myvenv)$ git push heroku master
(myvenv)$ heroku ps:scale web=1
(myvenv)$ heroku run python manage.py migrate
(myvenv)$ heroku open

参考

Django、静的ファイル、メディアファイルをAWS S3で管理
[Django] ファイルアップロード機能の使い方 [クラウドストレージ編]
DjangoアプリをHerokuにデプロイする時のエラー対処 whitenoise編
DjangoアプリをHerokuにデプロイする[その1]
[Django] Heroku デプロイ方法 2018年版
Django Girls Tutorial

25
28
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
25
28