Django + Wagtail + Puputの小説アプリケーションのベース作成

## 前回までのあらすじ
PythonなWebフレームワークのDjangoの開発環境をコンテナで作成することに成功し、機械学習用の環境構築を実施したコンテナ初心者。その環境を用いて社内外で休み時間中にWebフレームワークではない生のPythonコードとふれあい、Pythonの構造を少しずつ把握していく。そして、社内で本格的にDjangoアプリケーションを開発する道へ進んでいく......

[Qiita: 3.docker-composeを使用したコンテナでの開発環境セットアップ(Django)](https://qiita.com/GCkurabe/items/0073c279481a4db6696e)

[Qiita: 4.VMのdocker-composeとAtomのHydrogenでJupyter notebook風の機械学習の環境を構築する](https://qiita.com/GCkurabe/items/78c6e7ec9ae27cea374a)

## 今回の内容
今回はコンテナを駆使してDjangoのアプリケーション開発を行います。私も実際にこの知見で社内で独学アンド単独でver0.1のアプリケーションの作成に成功し、実際にプロトタイプ公開として動作させるに至っております。そこで得た情報や踏みまくったOops、ヒヤリハット、オペミスをDjangoやDockerのコードに反映していきたいと思います。

そして、せっかく小説を書いたりしているのでうまいことそれに関連した「個人利用小説投稿サイト」という題目でアプリを作っていきたいと思います。要するにDjango Girlsとかのブログ投稿サイトみたいなのを、もう少し小説サイトっぽく作れるかということを試してみたいと考えております。

で、ブログ投稿サイトということならWordPressのようなCMSを使用することができればより高品質で簡単にwebアプリケーションを構築できるのではないかと考えました。これらをうまく合体させていけば、アプリケーションの開発者は私ひとりであっても対応は続けることができそうな気がします。オフタイムプログラマーとって、これは大事なことです。今回はDjango用のCMSとしてWagtailというものとPuputというものを使用して、ベースとなる部分を作成しようと思います。

## 今回のソースコード

GitHubでそのままgitcloneして起動すれば使用できるようにplaneブランチを切って公開しました。

[GitHub: https://github.com/kurawo/Distributed-Novel-Application-by-Git/tree/plane](https://github.com/kurawo/Distributed-Novel-Application-by-Git/tree/plane)

あくまで個人のみの使用目的です。このため本番環境での使用は非推奨で、このアプリによって起きた損害の責任を負うことはできません。あくまで個人でのWebアプリの動作確認などにお使いください。使用するためにはVirtualBox, Vagrant, Docker, Docker-Composeが必要となります。cloneしたあとでのデプロイ方法の簡単な手順は以下のURLをご確認ください。

[GitHub wiki: https://github.com/kurawo/Distributed-Novel-Application-by-Git/wiki](https://github.com/kurawo/Distributed-Novel-Application-by-Git/wiki)

詳しいアーキテクチャや構成の考え方などについては前提条件をご確認ください。

## 前提条件
事前に前回の記事と同一もしくはそれに準ずる環境、すなわちdocker-composeを使用可能な環境の準備をお願いいたします。私の書いてきたこの3つの記事は環境構築において参考になると思います。とにかく環境構築に苦しむ方にはおすすめしております。これでもいろいろな苦しみがありましたが......

[Qiita: 1.VirtualBox + Vagrant + DockerによるOSに縛られないコンテナ環境セットアップ](https://qiita.com/GCkurabe/items/151c2a57688c03cfbdd8)

[Qiita: 2.docker-composeを使用したコンテナでの開発環境セットアップ(CakePHP3)](https://qiita.com/GCkurabe/items/d1d49e08b5666d30d3b1)

[Qiita: 3.docker-composeを使用したコンテナでの開発環境セットアップ(Django)](https://qiita.com/GCkurabe/items/0073c279481a4db6696e)

また、今回具体的なPythonコードを書いていきますので、「Pythonよくわからない」な人は以下の本を買って読みながら進めてもらうといいかもしれません。私もここに書いてあるプレーンなソースコードはだいたい試して理解していきました。

[オライリー: 入門 Python 3 単行本（ソフトカバー） https://www.amazon.co.jp/dp/4873117380/ref=cm_sw_em_r_mt_dp_U_QOTJDbJNJG5F1](https://www.amazon.co.jp/dp/4873117380/ref=cm_sw_em_r_mt_dp_U_QOTJDbJNJG5F1)

この本のソースコード実行には、以下の環境で行なっています。機能的にはオーバースペック気味だとは思いますが、気軽に機械学習にも使えるのでおすすめです。

[Qiita: 4.VMのdocker-composeとAtomのHydrogenでJupyter notebook風の機械学習の環境を構築する](https://qiita.com/GCkurabe/items/78c6e7ec9ae27cea374a)

しかし最近だとGoogleが「Google Colaboratory」というJupyter notebookのWebサービスを提供しており、ここではwebブラウザを用意するだけでpythonコードを試すことができます。業務上のデータを使わないならとてもオススメです。

ということを書くため、試しに触ってみましたがなんと自分の使っているアカウントで自動でログインしてくれてプログラムを実行することができました、なんじゃこれは......

```
Google Colaboratory　で検索。
```

## 今回の使用環境

- macOS Mojave 10.14.5
- Atom 1.37
- Hydrogen 2.10.3
- VirtualBox 6.0.4
- Vagrant 2.2.4
- CentOS Linux release 7.6.1810 (Core)
- Docker 18.09.6
- docker-compose 1.24.0

以下からはどのような手順でこの環境を構築したかの内容となります。

## Django用のDocker-composeファイルの配置と修正
以前、私は以下の記事でDjango用の環境構築は実施しました。

[Qiita: 3.docker-composeを使用したコンテナでの開発環境セットアップ(Django)](https://qiita.com/GCkurabe/items/0073c279481a4db6696e)

この中のDocker-compose用の設定ファイルを以下の記事を書いてくださった方のものを使わせていただいていたおりました。

[Qiita:DjangoをDocker Composeでupしよう！](https://qiita.com/kyhei_0727/items/e0eb4cfa46d71258f1be)

[GitHubのリポジトリ: https://github.com/kyhei/docker-django](https://github.com/kyhei/docker-django)

ですが、実際にアプリケーション開発に入り、modelの記述を行い、コンテナ起動中にmigrationを実行していたとき、migrationファイルがdocker-compose downのたびに消し飛んでいる事象が確認されました。migrationが実行できなくなっていたのです。

とりあえずfakeのmigrationコマンドを打つことで回避できることはわかったのですが、精神衛生上あまりよろしくないのでdjangoのソースコードはコンテナ起動中においてもVMでもコンテナでも共有するようにしました。それがdocker-compose.ymlの、以下の13行目の内容となります。

```
version: '3.7'
services:
  django:
    restart: always
    build: ./django
    expose:
      - "3031"
    depends_on:
      - postgres
    command: bash -c "python manage.py migrate && gunicorn my_docker_project.wsgi -b 0.0.0.0:3031"
    volumes:
      - "staticdata:/opt/static/"
      - "./django:/opt/apps" # 2019/09/28 kurawo add
# 以下省略
```

「./django」のところがVMでのディレクトリの場所で、「/opt/apps」がdjangoコンテナでのディレクトリの場所を意味しています。これでコンテナ上で実行されるときのmigrationファイルは残るようになります。これでとりあえずの前提条件は整いました。

## CMSフレームワークの準備

本来のスタート手順をみると、結構簡単に「pip install wagtail」と打っているだけだったりします。つまりこれだけで動くようになるようです。

[wagtail公式ドキュメント:http://docs.wagtail.io/en/v2.6.2/getting_started/tutorial.html](http://docs.wagtail.io/en/v2.6.2/getting_started/tutorial.html)

しかしそうは問屋がおろしません。今回のようにDockerとその管理を行うDocker-composeで「マイクロサービスアーキテクチャ」と、いかなる環境でも移植でき、動作しうるようにするための「Infrastructure as code」を指向する場合、可能な限りファイル群のどこかに環境を定めるためのコマンド(それこそpipなど)を書き込んでおく必要があります。

これはインフラ屋としてスノーフレークマシンを作り続け、マシンの破壊をもたらしてきた私の贖罪、つまりはただの意地ですが......

この方の以下の記事を参考に、現在のdockerファイル群を編集していくことにします。

[Qiita:Docker + Django + Wagtail を使ってCMS構築する - 導入編　https://qiita.com/masa0209/items/e3f632054b4da0ee9e35](https://qiita.com/masa0209/items/e3f632054b4da0ee9e35)

具体的にはdocker-compose.ymlとDockerfileを直していくやりかたとなります。今回特に必要なのはwagtailのインストールです。これを実施するためにこのdockerファイル群で編集をかけるべきなのは、「django」ディレクトリの中にある「requirements.base.txt」です。というのも、同一フォルダ内にある「Dockerfile.base」において以下の記述が行われているからです。

```
RUN pip install --no-cache-dir -r $APP_PATH/requirements.base.txt
```

つまり、この「requirements.base.txt」をもとにpipインストールをしているので、ここに追記するだけでよいということになります。

実際に以下の5行目と6行目のように追記します。6行目のものはpuputというブログを管理するためのDjangoアプリです。

[GitHub: puput: https://github.com/APSL/puput](https://github.com/APSL/puput)

[puputセットアップ手順: https://puput.readthedocs.io/en/latest/setup.html](https://puput.readthedocs.io/en/latest/setup.html)

それとDjangoもバージョンが少し上でないといけないとエラーに出くわしたので一行目も2.2に変更します。ちなみに現在は2.2.4と書き直しております。

```
Django==2.2
gunicorn==19.9.0
psycopg2==2.7.5
psycopg2-binary==2.7.5
wagtail==2.6.2
```


では早速、以下のコマンドでDockerfile.base内のpipを動かします。

```
# docker build -t django2.1 -f ./django/Dockerfile.base ./django
```

うまくいったようです。

```
Successfully built a3614b12038b
Successfully tagged django2.1:latest
```

コンテナ群を起動してみます。-dは裏側でコンテナを動作させ続けるために使用します。

```
# docker-compose up --build -d
```

ビルドが完了したのでバージョンアップが必要でない限りは以下のコマンドで起動すれば良いです。私は上のやつを特に理由もなく何度も打ち込んでVMのディスク容量いっぱいにしてしまいましたので注意です。

```
# docker-compose up -d
```

コンテナの中でコマンドを実行するために以下のコマンドを実行します。

```
[VM]# docker-compose exec django /bin/bash
```

コンテナの中で以下のコマンドを実行します。

```
[Ctr]# wagtail start mysite
```

なんとこれでファイル群が作成されました。

そのあとでmysite/settings/base.pyのDATABASESの部分を以下のように変更しておきます。

```
DATABASES = {
    'default': {
        "ENGINE": "django.db.backends.postgresql_psycopg2",
        'NAME': 'postgres',  #作成時のデフォルト
        'USER': 'postgres',  #作成時のデフォルト
        'PASSWORD' : 'hogemojahogemoja', #作成時にdocker-compose.ymlで設定
        'HOST' : 'postgres', #コンテナのサーバ名
        'PORT' : 5432,
    }
```

以下の項目も追記を行います。

```
INSTALLED_APPS = [
中略
'puput',
```

さらにこちらも追記。

```
PUPUT_AS_PLUGIN = True
```

url.pyにも変更を反映させておきます。

```
from puput import urls as puput_urls

url(r'',include(puput_urls)),    #この１行を追加
url(r'', include(wagtail_urls)), #この記述が元からあるのでその上にとのことです
```

以下のコマンドを実行しておきます。

```
# cd mysite/
# pip install -r requirements.txt
```

そして以下のコマンドを実行し作成されたファイルでmigrationを行っておきます。staticファイルも行っているのはnginxも見える共有ディレクトリにcssを配置するためです。そしてスーパーユーザーもつくっておきます。

```
# python ./mysite/manage.py migrate
# python ./mysite/manage.py collectstatic
# python ./mysite/manage.py createsuperuser
```

するとさらにファイルが作成されます。

終わったら一度docker-composeを終了します。

```
[Ctr]# exit
exit
[VM]# docker-compose down
```

docker-compose.ymlの編集はさらに後述のmysiteというディレクトリでの処理のために10行目をコメントアウトしてさらに下の内容を記述しておきます。

参考：
[GunicornでDjangoを使用する方法](https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/gunicorn/)

```
#command: bash -c "python manage.py migrate && gunicorn my_docker_project.wsgi -b 0.0.0.0:3031"
command: bash -c "cd mysite && gunicorn mysite.wsgi -b 0.0.0.0:3031"
```

またdjangoのvolumesのところは以下のように一行目をコメントアウトして二行目を追加しておきます。これでVMとコンテナのデータをマウントして共有できます。

```
volumes:
  #- "staticdata:/opt/static/"
  - "./mysite/static:/opt/apps/mysite/static"
  - "./django:/opt/apps" # 2019/09/28 kurawo add
```

nginxでも共有する必要があるので以下のように配置するようにします。

```
volumes:
  - "./nginx/:/etc/nginx/"
  #- "staticdata:/opt/apps/static/"
  - "./mysite/static:/opt/apps/static/"
```

終わったらもう一度起動します。

```
# docker-compose up -d
```

この状態で以下のURLにアクセスできるようになります。

```
http://192.168.33.10
```

あとは以下のURLにアクセスすればブログを記入することができます。

```
http://192.168.33.10/admin/
```

# まとめ
とりあえず動く環境を作ることができ、またGitHubもついに始められました。ここからは実際に小説アプリケーションとして動かすためにガリガリコードを付け加えてみようと思います。