データ入りのMySQLやDynamoDBをローカルにさくっと用意する

## 概要

テーブルデータが入ったMySQL, DynamoDBの環境をローカルに作る手順をまとめています。
開発の時など、何かしらデータが入った環境をさくっと用意したい場合に役に立ちます。

また、MySQLとDynamoDBいずれもDockerを利用して、簡易に使い捨て＆再利用できるようにしています。


## MySQL編

### 前提

 - Mac OS X 10.15.4
 - Docker version 19.03.8
 - docker-compose version 1.25.4
 - mysql Ver 8.0.19 for osx10.15

Docker, docker compose, mysqlはインストール済みとします。複雑なことはしないので、ソフトウェアのバージョンはそんなに気にしなくても動くと思います。また、mysqlは`brew install mysql`でインストールできます。

### 手順概要

1. 必要なディレクトリを作成
2. Dockerfile, docker-compose.ymlを作る
3. MySQLに初期データを投入するためのsetup.sqlを作る
4. docker-composeで起動。ログインして確認


### 手順詳細

#### 1. 必要なフォルダを作成

作業フォルダで以下のコマンドを実行します。

```zsh:フォルダ作成
$ mkdir -p ./db/mysql_data ./db/mysql_init
```

#### 2. Dockerfile, docker-compose.ymlを作る

MySQLは初回起動時にrootユーザのパスワードなどの作業が発生するため、docker-composeを使ってそれら無しでも使えるようにします。

```dockerfile:Dockerfile
# mysqlのバージョンは適宜変更ください
FROM mysql/mysql-server:5.7

RUN chown -R mysql /var/lib/mysql && \
    chgrp -R mysql /var/lib/mysql
```

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

services:
  mysql:
    container_name: mysql
    build:
      context: .
      dockerfile: ./Dockerfile
    hostname: mysql
    ports:
      - "3306:3306"
    volumes:
      - ./db/mysql_init:/docker-entrypoint-initdb.d
      - ./db/mysql_data:/var/lib/mysql
    environment:
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: DB01
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci --skip-character-set-client-handshake
```

ソースの通りですが構成内容は以下の通りです。

 - ローカルのポート番号は3306
 - デフォルトで作成するユーザやパスワード、データベースは`environment`に記載の通り

#### 3. MySQLを初期化するためのsetup.sqlを作る

```sql:./db/mysql_init/setup.sql
create table students (id varchar(4), name varchar(20), score int);
insert into students values ('1001', 'Alice', 60);
insert into students values ('1002', 'Bob', 80);
commit;
```

MySQLでは、`docker-entrypoint-initdb.d`フォルダにあるsqlが初期化で実行されます。そのため、`./db/mysql_init`の配下に初期化SQLを置いて、コンテナ内のdocker-entrypoint-initdb.d`にコピーされるようにします。

Dockerfileなどと合わせて以下の構成となっていればOKです。なお、`mysql_data`にはコンテナ内で作成されたDBのデータが保存されます。

```zsh:フォルダ構成
$ tree
.
├── Dockerfile
├── db
│   ├── mysql_data
│   └── mysql_init
│       └── setup.sql
└── docker-compose.yml
```


#### 4. docker-composeで起動。ログインして確認

```zsh:dockerコマンド
$ docker-compose build
$ docker-compose up
```

```zsh:コンテナへログイン
$ docker exec -it mysql bash
bash-4.2# mysql -u user -p
Enter password:    # パスワードはpassword
```

```sql:疎通確認
mysql> select * from DB01.students;
```

データが表示されればOKです。その他、コンテナを停止するときや削除するときのコマンドは以下の通りです。

```zsh:コンテナを起動停止する時
$ docker-compose stop
$ docker-compose start
```

```zsh:コンテナを削除する時
$ docker-compose down
```

```zsh:Macから疎通確認するとき
# 127.0.0.1の指定が必要
$ mysql -h 127.0.0.1 -u user -p
```


## DynamoDB編

### 前提

 - Mac OS X 10.15.4
 - Docker version 19.03.8
 - Python 3.8.2


### 手順概要

1. DockerでDynamoDBコンテナを起動
2. データ投入用のjsonファイルを用意
3. テーブル作成＆データ投入のスクリプトを実行

#### 1. DockerでDynamoDBコンテナを起動

```zsh:8000番ポートで起動
$ docker run -p 8000:8000 amazon/dynamodb-local
```

#### 2. データ投入用のjsonファイルを用意

```json:sampledata.json
[
    {
        "id" : "1001",
        "name" : "Alice",
        "score" : 60
    },
    {
        "id" : "1002",
        "name" : "Bob",
        "score" : 80
    }
]
```

#### 3. テーブル作成＆データ投入のスクリプトを実行

スクリプトは投入するデータに応じて適宜書き換えてください。

```python:CreateTable.py
from __future__ import print_function
import boto3
import json
import decimal


dynamodb = boto3.resource('dynamodb', region_name='ap-northeast-1', endpoint_url="http://localhost:8000")

table_name = 'Students'  #Studentsテーブル

# テーブルの作成
table = dynamodb.create_table(
    TableName=table_name,
    KeySchema=[
        {
            'AttributeName': 'id',
            'KeyType': 'HASH'  #Partition key
        }
    ],
    AttributeDefinitions=[
        {
            'AttributeName': 'id',
            'AttributeType': 'S'
        }
    ],
    ProvisionedThroughput={
        'ReadCapacityUnits': 5,
        'WriteCapacityUnits': 5
    }
)

print("Table status:", table.table_status)

table = dynamodb.Table(table_name)

# jsonファイルからデータを読み込みテーブルに更新
with open("sampledata.json") as json_file:
    stundents = json.load(json_file, parse_float = decimal.Decimal)
    for stundent in stundents:
        student_id = stundent['id']
        name = stundent['name']
        score = int(stundent['score'])

        table.put_item(
           Item={
               'id': student_id,
               'name': name,
               'score': score,
            }
        )
```

```zsh:作成したテーブルとデータの作成確認
$ aws dynamodb scan --endpoint-url http://localhost:8000 --table-name Students
```

## 参考

 - [amazon/dynamodb-local](https://hub.docker.com/r/amazon/dynamodb-local)
 - [Python および DynamoDB を使用して開発の開始方法](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/GettingStarted.Python.html)