docker-composeでFastAPIとMySQLとphpMyAdminの環境作ったら開発しやすすぎた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556658/6ec16fbf-ad49-b975-cf6a-642ab0476747.png)

## はじめに
株式会社マイスター・ギルド新規事業部のヒツジーです。
弊社新規事業部では、新規サービスの立ち上げを目指して
日々、アイディアの検証やプロトタイプの作成などを行っています！

技術の進歩は目覚ましいので、置いてかれないように新しい技術のキャッチアップにもいそしんでいます！
本記事は、FastAPI(Python)とMySQLとphpMyAdminのコンテナをdocker-composeを使って立ち上げたらいい感じの開発環境が手に入ったよ、ということを共有させていただく内容となっております。

本記事で紹介するコードは[こちらのGithub](https://github.com/NozawaYoshitaka/clean-architecture-like-fastapi)で公開しています。
ご使用は趣味の範囲でお願いします。何かありましても責任は負えません。

## どんな環境が手に入るのか？
```
$ docker compose build
$ docker compose up -d
```
のコマンドを実行すると、コンテナが複数立ち上がり、FastAPIで作成したAPIサーバーとphpMyAdminの２つが使えるようになります。

### FastAPIのAPIテンプレート
`http://localhost:8000/docs`にブラウザで問い合わせると、次のようなSwaggerUIの画面が表示されます。
FastAPIは実装したAPIの内容をもとに自動でAPI仕様書を作成してくれます。
API仕様書がわかるだけでしょ？と思うことなかれ、**SwaggerUIの利点は動作確認ができること**にあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556658/4d7721c5-b290-0484-fd23-030c30a4cb9e.png)

例えば、この `GET`メソッドのpathが `/api/users` のAPIを実行したいと思ったら、この「Execute」ボタンをクリックするだけで済みます。
Postmanなどの別のアプリを立ち上げて、pathを入力して、あーだこーだのあの手続きが不要になります！めっちゃ便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556658/8cb65a71-dd55-cf2e-f06d-43c712e569b1.png)

### phpMyAdmin
`http://localhost:8080`にブラウザで問い合わせると、次のようなphpMyAdminの画面が表示されます。
Dockerコンテナを立ち上げるだけで、DBクライアントに簡単につながるんです！！楽～
DBクライアントをわざわざ用意して、接続情報をもとにDBに接続する作業がこれで不要です。

APIの開発中はいろんなデータの場合で動作確認をしたいと考えると思いますが、それもGUIで簡単にデータをいじれるので実現します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556658/bb1704d2-0cc1-533b-d371-da2ea3d96cce.png)

## docker-compose.ymlの中身
以上のように、めっちゃ開発しやすい環境を準備できたんですが、その中身が気になると思います。
以下が docker-compose.yml の中身になります。

```yaml:docker-compose.yml
version: "3"

services:
  python-api:
      container_name: python_host
      build: ./docker/python
      volumes:
        - .:/src
      ports:
        - "8000:8000" # ホストマシンのポート8000を、docker内のポート8000に接続する
      environment:
        PMA_HOST: db
      networks:
        - mysql_bridge

  mysql:
    container_name: mysql_host
    build: ./docker/mysql
    command: --character-set-server=utf8 --collation-server=utf8_unicode_ci
    ports:
      - "3306:3306"
    environment:
      MYSQL_DATABASE: testdb
      MYSQL_ROOT_PASSWORD: password
      MYSQL_USER: user_name
      MYSQL_PASSWORD: password
    volumes:
      - ./docker/mysql/initdb.d:/docker-entrypoint-initdb.d # 定義どおりにテーブル作成
      - ./docker/mysql/conf.d:/etc/mysql/conf.d # MySQLの基本設定(文字化け対策)
#      - ./docker/mysql/mysql_data:/var/lib/mysql
    restart: always
    platform: linux/amd64
    networks:
      - mysql_bridge

  phpmyadmin:
    container_name: phpmyadmin_host
    depends_on:
      - mysql
    image: phpmyadmin/phpmyadmin
    restart: always
    ports:
      - "8080:80" #localhost:8080 で phpMyAdmin にアクセスできます
    environment:
      PMA_ARBITRARY: 1
      PMA_HOST: mysql_host
      PMA_USER: user_name
      PMA_PASSWORD: password
    networks:
      - mysql_bridge

# コンテナ間で通信を行うためのネットワークブリッジ
networks:
  mysql_bridge:
    driver: bridge
```

DBはMySQLを採用しています。
MySQLのコンテナを立ち上げる際にちょっと一工夫として、`initdb.d`フォルダ内のsqlを自動で実行するようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556658/180125f5-c9a3-7071-2f6c-b99feb66fd5d.png)

例えば、users.sqlの中身は以下のようなcreate tableとinsert文が書かれたものになっています。
これによりコンテナの立ち上げ時に毎回DBが初期化されます。
データの永続化はあえてしていません。私の好みで。
共同開発を行っているときに、他の人がデータをいじったかいじってないかなどの状態を確認しづらくなるのは嫌なので、データは`initdb.d`フォルダ内のsqlファイルを見ればわかる状態にしたかったからです。

```sql: users.sql
--
-- テーブルの作成
--
CREATE TABLE IF NOT EXISTS `users` (
  `user_id` binary(16) NOT NULL,
  `user_name` varchar(20) NOT NULL DEFAULT '',
  `mail_address` varchar(50) NOT NULL DEFAULT '',
  `password` varchar(20) NOT NULL DEFAULT '',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

--
-- テストデータのインサート
--
INSERT INTO `users` (`user_id`, `user_name`, `mail_address`, `password`) VALUES
(ULID_DECODE('01G921E9GQVWZN4MRWYJSS21P3'), '毎日 寝太郎', 'test_user1@test.com', 'password1'),
(ULID_DECODE('01GB6SC5PDBEC0PFDFHJ913QZ5'), '車田 テスラ', 'test_user2@test.com', 'password2'),
(ULID_DECODE('01GB6SC9BH6RF5NCXA0887Q5C9'), '金　肉尾', 'test_user3@test.com', 'password3');
```

## さいごに
良い感じの開発体験を得られるので、ぜひ試してみてください！
FastAPIのアーキテクチャについても書きたかったですが、紙面と時間が足りないので、ここでは割愛させていただきました。
READMEにちょっと書いてるので、気になる方はそちらをお読みください。

以上、docker-composeでFastAPIとMySQLとphpMyAdminの環境作ったら開発しやすすぎたでした。