Django x Docker

本稿ではDocker Composeを使って簡易なDjango/MySQLアプリケーションをセットアップして実行する方法を記しています。

**前提となる知識**
・terminalのコマンド操作
・viまたはエディタの操作
・MySQLの知識
・Dockerの知識

**前提条件**
・docker-composeがインストールされていること
・MySQLをインストールされていること
・Python3系がインストールされていること
・pipがインストールされていること

## プロジェクトコンポーネントを定義する
Docker Composeを使ってDjango/MySQLアプリケーションをセットアップするためにDockerfile,Python依存ファイル,docker-compose.ymlを作成します。
###1.任意の場所に空のプロジェクトを生成する

```terminal:terminal
$ mkdir docker_django
```

### 2.作成したプロジェクトの中で`Dockerfile`というファイルを作成する
### 3.以下のコードを`Dockerfile`に追加する

```dockerfile:Dockerfile
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir -p /var/www/docker_django
WORKDIR /var/www/docker_django
ADD requirements.txt /var/www/docker_django/
RUN pip install -r requirements.txt
ADD . /var/www/docker_django/
```

### 4.`Dockerfile`を保存して閉じる
### 5. 同プロジェクト内に`requirements.txt`というファイルを作成する
### 6. 以下の内容を`requirements.txt`に追加する

```text:requirements.txt
Django>=2.0.1
mysqlclient
```
### 7. requirements.txtを保存して閉じる
### 8. 同プロジェクト内に`docker-compose.yml`というファイルを作成する
### 9.以下の内容を`docker-compose.yml`に追加する

```yml:docker-compose.yml
version: '3'

services:
 db:
   image: mysql:5.7
   command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
   volumes:
   - .:/var/www/docker_django
   restart: always
   environment:
     MYSQL_ROOT_PASSWORD: root
     MYSQL_DATABASE: app_docker_django
     MYSQL_USER: root
     MYSQL_PASSWORD: root
 web:
   build: .
   command: sh -c "./wait-for-it.sh db:3306; python3 manage.py runserver 0.0.0.0:8000"
   volumes:
   - .:/var/www/docker_django
   ports:
   - "8080:8000"
   depends_on:
   - db
```

### 10.`docker-compose.yml`を保存して閉じる

ここまで行うとプロジェクトの中身は状態になる

```terminal:terminal
$ tree
.
├── Dockerfile
├── docker-compose.yml
└── requirements.txt
```

ここまででDocker ComposeでDjango/MySQLアプリケーションを作るためにDockerfile,Python依存ファイル,docker-compose.ymlを作成した。
Djangoプロジェクトを作成する

## Djangoプロジェクトを作成
### 1.　プロジェクト用の仮想環境を作り、仮想環境に入り、その中にDjangoの最新版を入れる

```terminal:terminal
$ python -m venv env_docker_django
$ . env_docker_django/bin/activate
(env_docker_django) $ pip install Django==2.0.5
Collecting Django==2.0.5
・
・
・
Successfully installed Django-2.0.5 pytz-2018.4
(env_docker_django) $ 
```

pip listでenv環境に入っているパッケージを確認できます。(env環境からdeactivateすると切り替わります。)

```terminal:terminal
(env_docker_django)$ pip install --upgrade pip
(env_docker_django)$ pip list
Package    Version
---------- -------
Django     2.0.5  
pip        10.0.1 
pytz       2018.4 
setuptools 28.8.0
(env_docker_django)$ 

```

### 2. `docker-compose run`を使うことでDjangoプロジェクトを作ります

```terminal:terminal
(env_docker_django) $ sudo docker-compose run web django-admin.py startproject docker_django .
Password:
Pulling db (mysql:5.7)...
5.7: Pulling from library/mysql
・
・
・
・
Successfully tagged docker_django_web:latest
(env_docker_django) $ 
```

### 3. `docker-compose`コマンドを実行後、プロジェクトのリストを確認してみましょう
```terminal:terminal
(env_docker_django) $ ls -l
 drwxr-xr-x 2 root   root   docker_django
 -rw-rw-r-- 1 user   user   docker-compose.yml
 drwxr-xr-x 7 user  staff   env_docker_django
 -rw-rw-r-- 1 user   user   Dockerfile
 -rwxr-xr-x 1 root   root   manage.py
 -rw-rw-r-- 1 user   user   requirements.txt
```
もしあなたがDockerをLinux上で起動させているなら、django-adminによって作られたファイルはrootに所有されてしまいます。
所有者を変更しましょう。※$USERはあなたのユーザ名です

```terminal:terminal
(env_docker_django)$ sudo chown -R $USER:$USER .
```

もしあなたがMac OSかWindows OSで起動させているのならば、既に所有権が存在しているはずです。

```terminal:terminal
 (env_docker_django)$ ls -l
 total 32
 -rw-r--r--  1 user  staff  Dockerfile
 drwxr-xr-x  6 user  staff  docker_django
 -rw-r--r--  1 user  staff  docker-compose.yml
 drwxr-xr-x  7 user  staff  env_docker_django
 -rwxr-xr-x  1 user  staff  manage.py
 -rw-r--r--  1 user  staff  requirements.txt
```

ここまで行うと以下の状態になっていると思います。

```terminal:terminal
(env_docker_django)$ tree
.
├── env_docker_django
│   ├── bin
・　　　　　　　・　　　　　├── activate
・　　　　　　　・　　　　　　・
・　　　　　　　・　　　　　　・
├── docker_django
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── docker-compose.yml
├── Dockerfile
├── manage.py
└── requirements.txt

```

ここまででDjangoプロジェクトを作成した。
MySQLのDBに接続する。

## データベースに接続する

### 1.`docker_django/settings.py`を編集します
### 2.`DATABASES = ...`を以下に置き換えます

```python:setting.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'OPTIONS': {
            'read_default_file': 'path/to/my.cnf',
        },
        'HOST': 'db',
        'PORT': 3306,
    }
}
```

プロジェクト直下にmy.cnfを作ります。
my.cnfは任意の場所に置けばいいですが、この場合プロジェクト直下のpath/to/に置いています。
my.cnfにはmysqlのdatabase,user,root,passwordを記載します。

### 3.`setting.py`を保存して閉じます

### 4.`docker-compose up -d`を実行します
`docker-compose up -d`を実行する前にdbの接続が失敗してwebが先に立ち上がるのを防ぐため[wait-for-it](https://github.com/vishnubob/wait-for-it)をダウンロードし、プロジェクトトップに置きます。

```terminal:terminal
(docker_django_env)$ docker-compose up -d
docker_django_db_1 is up-to-date
docker_django_web_1 is up-to-date
```

以下で動作確認します。
[http://localhost:8080/](http://localhost:8080/)

### 5.アプリケーションのDBを作る
・migrateする

```terminal:terminal
(docker_django_env)$ docker-compose run web python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
・
・
・
(docker_django_env)$ 
```

・管理者を作成する

```terminal:terminal
(docker_django_env)$ docker-compose run web python manage.py createsuperuser
Starting docker_django_db_1 ... done
Username (leave blank to use 'root'):
Email address: 
Password: 
Password (again): 
Superuser created successfully.
(docker_django_env)$ 
```

### 6.DBに入り作成されたデータを確認する

・docker-compose psでコンテナ名を確認し、dbの方を控える。execコマンドを使いdockerに入りましょう。(-itオプションはdockerの標準入出力と接続するコマンドです。)

```terminal:terminal
(docker_django_env)$ docker-compose ps
        Name                      Command               State           Ports         
--------------------------------------------------------------------------------------
docker_django_db_1    docker-entrypoint.sh mysql ...   Up      3306/tcp              
docker_django_web_1   sh -c ./wait-for-it.sh db: ...   Up      
・
・
・
(docker_django_env)$ docker exec -it docker_django_db_1 bash
$:/#
$:/# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor. 
・
・
・
```

・migrateとcreatesuperuserでできたテーブルと中身を確認する

```terminal:terminal
mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| docker_django      |
　　　　　　　　　　　　　　　　　　　　　・
　　　　　　　　　　　　　　　　　　　　　・
　　　　　　　　　　　　　　　　　　　　　・
+--------------------+

mysql> USE docker_django;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW TABLES;
+------------------------------+
| Tables_in_docker_django |
+------------------------------+
| auth_group                   |
　　　　　　　　　　　　　　　　　　　　・
　　　　　　　　　　　　　　　　　　　　・
　　　　　　　　　　　　　　　　　　　　・
| django_admin_log             |
　　　　　　　　　　　　　　　　　　　　・
　　　　　　　　　　　　　　　　　　　　・
　　　　　　　　　　　　　　　　　　　　・
+------------------------------+
mysql> SELECT * FROM auth_user;
+----+--------------------------------------------------------------------------------+------------+--------------+----------+------------+-----------+--------------------+----------+-----------+----------------------------+
| id | password | last_login | is_superuser | username | first_name | last_name | email            | is_staff | is_active | date_joined                |
+----+--------------------------------------------------------------------------------+------------+--------------+----------+------------+-----------+--------------------+----------+-----------+----------------------------+
|  1 |   ***    | NULL       |            1 |   ***    |            |           | *****            |        1 |         1 | 　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　 |
+----+--------------------------------------------------------------------------------+------------+--------------+----------+------------+-----------+--------------------+----------+-----------+----------------------------+

```

・Dockerを抜ける

```terminal:terminal
mysql> exit
Bye
$:/# exit
exit
(docker_django_env) 
```

・以下で動作を確認できます
[http://localhost:8080/admin/](http://localhost:8080/admin/)
<img width="1233" alt="スクリーンショット 2018-05-20 21.45.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/126098/d4bc2fa3-9c42-0302-42f5-545c253a9dc4.png">

<img width="1248" alt="スクリーンショット 2018-05-20 21.46.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/126098/c0b57ac1-ef1b-1fec-d93a-b1afe69a5b56.png">

参考サイト
[Quickstart: Compose and Django](https://docs.docker.com/compose/django/#define-the-project-components
)