【２０２１年度１０月版】Django REST frameworkをDockerで動かす（Pipenv、MySQL、pre-commit導入）

皆さん一度は聞いたことがあるであろうPythonの代表的なフレームワークDjango。

先週ぐらい前に初めて触れたのですが、開発効率がとんでもなく上がりますね。

なんといってもREST APIの構築がかなり簡単に行なえますし、今までAPIの構築をAPI GatewayやLambdaで構築していたのが時間の無駄だったのではないかと思うようになりました。

MySQL、Oracle、PosgreSQLなどのデータベースも豊富用意されていますし、今後はサーバーサイドの開発はDjangoで開発することが増えてきそうですね。

そんなDjangoをDockerで動かしてみようという記事になります。

私自身、Djangoに触れてからわずか１週間しか経っておらず、普段はフロントエンドを中心に開発しておりますので、記事の内容に不備がある可能性がございますのでその点はご了承下さい。

# 注意事項

- Python2系はどうやらサポートが終了してるそうなので。、Python3系を使用します。
- データベースはMySQLを使用しますが、他のデータベースを使用する場合はデータベースの設定の部分だけ適時変えて下さい。（インストールするライブラリとデータベースの設定ファイルを変えるだけなので、そこを変えたからと言ってエラーが出るということはほぼ無いと思います。）
- Macでの環境を前提に話を進めていきます。
- APIやDBの設定の説明などは、既に記事を出している方も多いので省きます。

また、筆者の環境は以下になります。

|項目|バージョン|
|---|---|
|OS|Big Sur v11.6（M1チップ）|
|python3|3.9.7|
|pip|21.3|
|dokcer|20.10.8|

それでは、多少長めの記事となっておりますが頑張っていきましょう！

# 事前準備

DjangoをDockerで動かす前に、まずは、必要なものをインストールしておきましょう。

## Python・Pipコマンド確認

バージョン確認などでPython3コマンドとPipコマンドが使えるかの確認。

```terminal
$ python3 --version
$ pip --version
```

## Docker Desktop

Docker専用のデスクトップアプリをダウンロードして下さい。

ただし、プロセッサーがIntelの場合とM1の場合でダウンロードするファイルが違うので、下記のアドレスを参考に今一度ご自身のプロセッサーをご確認下さい。

[https://helpx.adobe.com/jp/download-install/kb/apple-silicon-m1-chip.html](https://helpx.adobe.com/jp/download-install/kb/apple-silicon-m1-chip.html)

下記のリンクから自分の環境に合ったDokcerをインストール。

|プロセッサー|バージョン|
|---|---|
|Intel|Mac with Intel chip|
|M1|Mac with Apple chip|

[https://docs.docker.com/desktop/mac/install/](https://docs.docker.com/desktop/mac/install/)

## VSCode拡張機能

拡張機能もインストール。

・[https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker)

Dockerはコンテナにアクセスするときに、長いコマンドを打つ羽目になるので上記の拡張機能をインストールしておくことをオススメします。

## MySQL

DjangoでMySQLを使用する場合``mysqlclient``というライブラリを使用するのですが、MySQLライブラリをインストールしていないとエラーが出るためインストール。

```terminal
$ brew install mysql
```

## Pipenv

プロジェクトごとにライブラリを管理するためにPipenvをインストール。

Nodeでいう``npm``や``yarn``のことです。

```terminal
$ brew install pipenv
$ pipenv --version
```

# Django環境構築

それでは本題のDjangoをDockerで動かしていきましょう。

Docker Desktopを立ち上げた上で行って下さい。（dockerコマンドが打てないため）

## 必要なライブラリのインストール

```terminal
$ pipenv install django
$ pipenv install djangorestframework
$ pipenv install django-filter
```

## Docker設定ファイル

```terminal
$ touch Dockerfile docker-compose.yml
```

### Dockerfile

```Dockerfile
FROM python:3.9
ENV PYTHONUNBUFFERED 1
WORKDIR /code
ADD Pipfile* /code/
RUN cd /code && \
    pip install -U pip && \
    pip install pipenv && \
    pipenv install --system --ignore-pipfile --deploy
COPY . /code/
```

### docker-compose.yml

```docker-compose.yml
version: '3'
services:
  db:
    platform: linux/x86_64
    image: mysql:8.0
    container_name: example_db
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: example-db
      MYSQL_USER: example
      MYSQL_PASSWORD: example-password
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
  web:
    build: .
    container_name: example_web_app
    command: python3 manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db
```

## Djangoプロジェクト作成

```
$ docker-compose run web django-admin.py startproject example .
```

この場合、``example``ディレクトリが作成され、このディレクトリを起点に設定などを行っていきます。

## MySQL設定

DjangoはデフォルトではSQLiteが使われているので、これをMySQLに変更。

```example/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'example-db',
        'USER': 'example',
        'PASSWORD': 'example-password',
        'HOST': 'db',
        'PORT': '3306'
    }
}
```

``docker-compose.yml``と値を一致させて下さい。

|docker-compose.yml|settings.py|
|---|---|
|MYSQL_ROOT_PASSWORD|なし|
|MYSQL_DATABASE|NAME|
|MYSQL_USER|USER|
|MYSQL_PASSWORD|PASSWORD|

## ローカルサーバー立ち上げ

ビルドして立ち上げます。（Pipenvで動かしているため少し時間がかかります）

```terminal
$ docker-compose up -d --build 
```

そして、[http://localhost:8000](http://localhost:8000)へアクセス。

もしローカルサーバーが立ち上がらない場合は、VSCodeの左側にDockerのマークがあると思うのでそこをクリック。（拡張機能をインストールしないと表示されない）

そこで、mysqlじゃない方を右クリックし「Restart」を選択。

するとローカルサーバーが起動します。

## MySQLにアクセス

VSCodeの左側のDockerのマークをクリック。

そのマークをクリックし、「mysql:8.0」で右クリック → 「Attch Shell」を選択。

```terminal
$ mysql -u root -p
> Enter password: docker-compose.ymlのMYSQL_ROOT_PASSWORDの値を入力
```

MySQLにアクセスできればOK。

試しにデータベースの一覧を表示してみましょう。

```mysql
mysql > show databases;
> docker-compose.ymlのMYSQL_ROOT_PASSWORDの値を入力

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| example-db         |
| sys                |
+--------------------+
5 rows in set (0.02 sec)
```

これでDjangoをDockerで動かすことが出来ましたね。

# 独自スクリプト・pre-commit導入

最後に快適な環境を手に入れるために独自スクリプトの追加とpre-commitを導入していきます。

## 独自スクリプト

VueやReactで開発するときってローカルサーバーを立ち上げる場合、``npm run start``などのコマンドを打ちますよね。

それらは``package.json``で定義されているのですが、それと同様にPipenvを使えば同じようにローカルサーバーを立ち上げたり、ビルドなども行えます。

現にビルドコマンドを追加してみます。

ディレクトリ直下の``Pipfile``に``[scripts]``を追加。

```Pipfile
[scripts]
build = "docker-compose up -d --build"
```

そしたら、``pipenv run``でこのコマンドを打ってみます。

```terminal
$ pipenv run build
```

すると、先程と同じようにビルドが開始されます。

あとは自分の好きなようにカスタマイズしてみて下さい！

## pre-commit

pre-commitを導入する前に、まずはflake8とautopep8を導入します。

### flake8

falke8とはPython版のESLintです。

とりあえずインストール。

```terminal
$ pipenv install --dev flake8
```

flake8をスクリプトで走らせてみましょう。

Pipfileのscriptsに追加。

```Pipfile
[scripts]
build = "docker-compose up -d --build"
lint = "flake8 ."
```

```terminal
$ pipenv run lint
```

### autopep8

お次はautopep8（Python版のPrettier）を導入しましょう。

```terminal
$ pipenv install --dev autopep8
```

同じようにスクリプトを追加し、走らせてみる。

```Pipfile
[scripts]
build = "docker-compose up -d --build"
lint = "flake8 ."
format = "autopep8 -ivr ."
```

```terminal
$ pipenv run format
```

また、PrettierやESLintと同様に自分好みの設定を施したい方は以下の記事が参考になります。

[Pipenv で flake8 / autopep8 を上手く使う](https://zenn.dev/ciloholic/articles/20bdb5a22be740)

### pre-commit導入

さて、最後にflake8とautopep8をGitでCommitする前に適用させるようにしていきましょう。

ちなみにpre-commitはPython版のHuskyみたいなものです。

```terminal
$ brew install pre-commit
$ pre-commit --version
```

そしたら、設定ファイルの作成。

```terminal
$ pre-commit sample-config > .pre-commit-config.yaml
```

プロジェクト直下に``.pre-commit-config.yaml``が作成され、中身を以下に変更。

```.pre-commit-config.yaml
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://gitlab.com/pycqa/flake8
  rev: 3.8.1
  hooks:
  - id: flake8
    args: [--ignore=E402, --max-complexity, "10", --max-expression-complexity=7, --max-cognitive-complexity=7]
    additional_dependencies: [flake8-bugbear, flake8-builtins, flake8-eradicate, pep8-naming, flake8-expression-complexity, flake8-cognitive-complexity]
- repo: https://github.com/pre-commit/mirrors-autopep8
  rev: v1.5.7
  hooks:
  - id: autopep8
    args: [--in-place, -r, --aggressive, --exclude, "manage.py,./*/migrations,./*/snapshots,./*,./**/__init__.py,hirameki/asgi.py", --max-line-length, "120"] 
```

以下のコマンドでgitにhooksを追加。

```terminal
$ pre-commit install
```

これでコミットする前に``flake8``と``autopep8``が走ります。

実際にコミットし、プッシュしてみましょう。

```terminal
$ git add .
$ git commit -m 'pre-commit動作確認'
$ git push
```

いかがだったでしょうか？

PipenvでPythonの環境構築を行ったのは今回が初めてなので、多少至らない部分もありますがその点はご了承下さい。

また、何か気になる点や間違っているところがあればコメント欄にて教えてくださると助かります。

エラーが出た場合もご気軽にご相談下さい！

以上、「【２０２１年度１０月版】Django REST frameworkをDockerで動かす（Pipenv、MySQL、pre-commit導入）」でした！

Thank you for reading

# 参考記事

以下、この記事を書くにあたって参考にさせていただいた記事となります。

・[2018年のPythonプロジェクトのはじめかた](https://qiita.com/sl2/items/1e503952b9506a0539ea)
・[Django REST Frameworkを使って爆速でAPIを実装する](https://qiita.com/kimihiro_n/items/86e0a9e619720e57ecd8)
・[Django+MySQLの開発環境をdocker-composeで構築する](https://qiita.com/bakupen/items/f23ce3d2325b4491a2dd)
・[【Python】Pipfile.lockを活用したDockerとpipenvでの安全な環境構築](https://blog.ikedaosushi.com/entry/2019/02/03/220213)
・[pre-commitでコミット時にコードの整形やチェックを行う](https://zenn.dev/yiskw713/articles/3c3b4022f3e3f22d276d)