PythonのフレームワークFlaskを使用してWebアプリ作成の物語（３）Docker登場　DBの準備

# このシリーズの目的
- PythonのフレームワークであるFlaskを使用してWebアプリに必要な機能の作成と解説をやります。
- 普段の勉強のアウトプットとして書いています。質問や指摘は大歓迎です。

## 前回まで
[PythonのフレームワークFlaskを使用してWebアプリ作成の物語（１）こんにちは世界
](https://qiita.com/penpenta/items/47d23e2ea1decb4fb252)
[PythonのフレームワークFlaskを使用してWebアプリ作成の物語（２）HTMLの表示とメソッドとパラメータの受け取りかた](https://qiita.com/penpenta/items/c73c974f302c3453bbec)


# 目的

- Flask で使用する DB（PostgreSQL） を Docker を使用して準備する
- DB を pgadmin4 で見れるようにする

## ソースコード
[GitHubに上げています](https://github.com/oq-Yuki-po/flask-tutorial/tree/chapter_003)

## 環境準備

### Docker 環境準備

  Mac の場合

  ```bash
    brew cask install docker
  ```

  ver 確認

  ```bash
    $ docker -v
      Docker version 18.09.1, build 4c52b90
  ```

### フォルダ構成

```bash
$ tree
.
├── README.md
├── docker-compose.yml
├── form.html
├── pgadmin
├── postgresql
│   ├── data
│   └── init
│       └── 1_create_db.sql
├── requirements.txt
└── src
    ├── main.py
    └── templates
        └── hello.html

```

## DB 作成

<details><summary>Dockerって何なの？？</summary><div>

ものすごく、ざっくり言うと
環境構築の技術の1つ
Dockerを使用することで、OSのインストールやプログラミングのための環境構築の手間が格段に減ります

以下の記事を見ると何となくイメージが湧くと思います。

[【図解】Dockerの全体像を理解する -前編-](https://qiita.com/kotaro-dr/items/b1024c7d200a75b992fc)

</div></details>

### docker-compose.yml の作成

```docker-compose.yml

version: "3"

services:

  postgresql:
    # イメージの指定
    image: postgres:10.5
    # コンテナの名前
    container_name: flask_tutorial_postgresql
    # hostのport5432とコンテナのport5432を繋ぐ
    # ホスト；コンテナ
    ports:
      - 5432:5432
    # hostとコンテナで共有するファイルやディレクトリを設定
    # ホストのディレクトリ；コンテナのディレクトリ
    volumes:
      # /docker-entrypoint-initdb.dはコンテナ初回起動時に実行されるスクリプトを置く場所
      - ./DB/init/:/docker-entrypoint-initdb.d
      # /var/lib/postgresql/dataはpostgresqlのデータが保存されている場所
      - /Users/${USER}/Volumes/flask_tutorial/postgres:/var/lib/postgresql/data
    # コンテナの環境変数設定
    environment:
      # スーパユーザ名(省略時は"postgres")
      POSTGRES_USER: ${POSTGRES_USER}
      # スーパユーザのパスワード(省略時はパスワードなしでログイン可)
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      # postgresqlの初期化時の文字コード
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8"
    # ホスト名
    hostname: postgres
    # Dockerを実行するユーザ
    user: root
    environment:
      TZ: "Asia/Tokyo"

  pgadmin4:
    image: dpage/pgadmin4:3.3
    container_name: flask_tutorial_pgadmin4
    ports:
      - 80:80
    volumes:
      - ./pgadmin:/var/lib/pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
      PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
    depends_on:
          - postgresql
    hostname: pgadmin4

```

### ポイント
`${POSTGRES_USER}`や`${POSTGRES_PASSWORD}`の`${}`は変数を表していて
docker-compose.ymlと同じ階層にある`.env`ファイルで変数を指定できる。

.envの例

```
POSTGRES_USER=root
POSTGRES_PASSWORD=root
PGADMIN_DEFAULT_EMAIL=root
PGADMIN_DEFAULT_PASSWORD=root
```

### コンテナ操作

`docker-compose.yml`があるディレクトリで`docker-compose up -d`実行

コンテナ起動

```bash
$ docker-compose up -d
Creating network "first_tutorial_default" with the default driver
Creating flask_tutorial_postgresql ... done
Creating flask_tutorial_pgadmin4   ... done
```

コンテナが起動できたか確認

```bash
$ docker ps -a
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                         NAMES
487182403fc2        dpage/pgadmin4:3.3   "/entrypoint.sh"         8 seconds ago       Up 6 seconds        0.0.0.0:80->80/tcp, 443/tcp   flask_tutorial_pgadmin4
1441abbc6c72        postgres:10.5        "docker-entrypoint.s…"   9 seconds ago       Up 7 seconds        0.0.0.0:5432->5432/tcp        flask_tutorial_postgresql
```

コンテナを落とす

`docker-compose.yml`があるディレクトリで`docker-compose down`実行

```bash
$ docker-compose down
Stopping flask_tutorial_pgadmin4 ... done
Removing flask_tutorial_pgadmin4   ... done
Removing flask_tutorial_postgresql ... done
Removing network first_tutorial_default
```


### 初回実行スクリプトについて

```1_create_db.sql
create database flask_tutorial;
```

#### ポイント
- ファイル名の先頭に数字を入れると、その順番で実行してくれる
  - 1_DB作成
  - 2_テーブル作成
  - 3_初期データ挿入

みたいな

- 今回は単純に`flask_tutorial`というDBを作成しているのみ

## DB 確認

### pgadmin4にアクセス

```docker-compose.ymlの一部抜粋
  pgadmin4:
    image: dpage/pgadmin4:3.3
    container_name: flask_tutorial_pgadmin4
    ports:
      - 80:80
    volumes:
      - ./pgadmin:/var/lib/pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
      PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
    depends_on:
          - postgresql
    hostname: pgadmin4
```

コンテナ起動を起動した状態で`http://localhost:80`にアクセスすると下記の画面が表示される

|<img width="1920" alt="スクリーンショット 2019-07-14 1.27.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/1e090ba1-0f12-2a73-e7e0-64675cea967e.png">|
|:-:|

#### ポイント
`Email Address`と`Password`は.env で設定した値

### サーバ接続
pgadmin4にログインすると以下のように表示される。

|<img width="1918" alt="スクリーンショット 2019-07-14 1.40.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/09032699-cb4d-42fa-904e-10651fe054fb.png">|
|:-:|
`Servers`を右クリック
`Servers`>`作成`>`サーバ...`を選択すると以下が表示されるので設定していく

|<img width="516" alt="スクリーンショット 2019-07-14 2.07.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/e44ed21a-386a-0aee-34ff-77cff7e5457f.png">|
|:-:|

|<img width="515" alt="スクリーンショット 2019-07-14 2.08.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/f7299111-87a7-6719-3631-2643aa849f56.png">|
|:-:|

#### ポイント

`ホスト名/アドレス`はホストのIPアドレスを調べて入力すること

### DB確認

flask_tutorialというDBが存在していることを確認

|<img width="1919" alt="スクリーンショット 2019-07-14 2.16.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/e56b7acd-26e8-7de5-3680-c77235e5bb91.png">|
|:-:|

## 躓いた所
- DBの初期化に失敗した場合（sql間違えたとか）はDB/dataのディレクトリを削除しないと、初期化が再度実行されない
- postgresqlのデータのマウント先はディレクトリの権限を確認しないと、DBがそもそも立ち上ってくれなくなる。


# 次回
- flaskでDBに接続してみよう