Docker覚書

[Prismaを使ってMySQLに接続するGraphQL APIサーバーを構築](https://qiita.com/yasuhiro-yamada/items/edd875dcc3385142bdbb)を試していて気付いたことの覚書。

# 前提
元記事に書かれていないことで、実施した作業。

## `graphql` パッケージのグローバルインストール

```
$ yarn global add graphql
```

[Prismaのデプロイ](https://qiita.com/yasuhiro-yamada/items/edd875dcc3385142bdbb#prisma%E3%81%AE%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4)で必要になるため。以下の設定ファイルに記載あり。

```yml:database/prisma.yml
hooks:
  post-deploy:
    - graphql get-schema
```

## Dockerイメージのバージョン変更

```diff:database/docker-compose.yml
version: '3'
services:
  prisma:
-   image: prismagraphql/prisma:1.23
+   image: prismagraphql/prisma:1.34.1
```

インストールしたPrisma CLIとコンテナ上のPrismaサーバーのバージョンが合わず、エラーになるため。

```
$ prisma deploy
Warning: Your Prisma server and Prisma CLI are currently out of sync. They should be on the same minor version.
  
Prisma CLI version: prisma/1.34.1 (darwin-x64) node-v11.1.0
Prisma server version: 1.23.4
  
For further information, please read: http://bit.ly/prisma-cli-server-sync
  
Creating stage default for service default !

ERROR: Whoops. Looks like an internal server error. Search your server logs for request ID: local:cjy7j59f5000h0834v7kpcfds

{
  "data": {
    "addProject": null
  },
  "errors": [
    {
      "message": "Whoops. Looks like an internal server error. Search your server logs for request ID: local:cjy7j59f5000h0834v7kpcfds",
      "path": [
        "addProject"
      ],
      "locations": [
        {
          "line": 2,
          "column": 9
        }
      ],
      "requestId": "local:cjy7j59f5000h0834v7kpcfds"
    }
  ],
  "status": 200
}

Get in touch if you need help: https://spectrum.chat/prisma
To get more detailed output, run $ export DEBUG="*"
```

# 検証
## Mysqlデータベースはどこに保存されているのか
`docker-compose.yml` にマウントするボリュームの**ディレクトリ**が記載されていないが、コンテナを再起動してもデータが永続して残っている。肝要の設定は以下の箇所。

```yml:database/docker-compose.yml
services:
  mysql:
    volumes:
      - mysql:/var/lib/mysql
volumes:
  mysql:
```

`/services/mysql/volumes` のコロン(:)前にあるmysqlと `/volumes` にある mysql が対応している。`/volumes/mysql` でディレクトリを指定していないため、特別なディレクトリにボリュームが作成されている。

```
$ docker volume ls
DRIVER              VOLUME NAME
local               database_mysql
$ docker volume inspect database_mysql
[
    {
        "CreatedAt": "2019-07-17T17:00:42Z",
        "Driver": "local",
        "Labels": {
            "com.docker.compose.project": "database",
            "com.docker.compose.version": "1.23.2",
            "com.docker.compose.volume": "mysql"
        },
        "Mountpoint": "/var/lib/docker/volumes/database_mysql/_data",
        "Name": "database_mysql",
        "Options": null,
        "Scope": "local"
    }
]
```

## `docker-compose up` の挙動
`docker-compose.yml` に記述されているボリュームの名前を変えると既存データベースのデータを読めなくなるものと仮定して、同ファイルの `mysql` を `mysql_test` に変えて `Ctrl+C` -> `docker-compose up` をしたが、既存データが読めてしまった。

`docker-compose up` の際のメッセージに答えがある。

```
WARNING: Service "mysql" is using volume "/var/lib/mysql" from the previous container. Host mapping "database_mysql_test" has no effect. Remove the existing containers (with `docker-compose rm mysql`) to use the host volume mapping.
```

なぜprevious containerのvolumeを使ってしまったのか。まず、`Ctrl+C` をした時のコンテナの挙動を確認してみる。

```
$ docker ps -a
CONTAINER ID        IMAGE                         COMMAND                  CREATED             STATUS                       PORTS               NAMES
c87b826a3e0a        mysql:5.7                     "docker-entrypoint.s…"   3 minutes ago       Exited (137) 2 seconds ago                       database_mysql_1
ec8e0042b196        prismagraphql/prisma:1.34.1   "/bin/sh -c /app/sta…"   3 minutes ago       Exited (137) 2 seconds ago                       database_prisma_1

```

コンテナが停止している。この状態で `docker-compose up` を実行すると以下のようになる。

```
$ docker ps -a
CONTAINER ID        IMAGE                         COMMAND                  CREATED             STATUS              PORTS                               NAMES
c87b826a3e0a        mysql:5.7                     "docker-entrypoint.s…"   3 minutes ago       Up 4 seconds        33060/tcp, 0.0.0.0:3333->3306/tcp   database_mysql_1
ec8e0042b196        prismagraphql/prisma:1.34.1   "/bin/sh -c /app/sta…"   3 minutes ago       Up 4 seconds        0.0.0.0:4466->4466/tcp              database_prisma_1
```

同じコンテナを再利用しているため、「設定ファイルではボリュームの情報が変わっているが、以前（すなわち初めて起動した時）のボリュームを継続して使う」ということのようだ。このような場合は、コンテナをdownさせてから再びupすれば、その時点での設定ファイルの内容が反映される。

```
$ docker-compose stop
^CGracefully stopping... (press Ctrl+C again to force)
Stopping database_mysql_1  ... done
Stopping database_prisma_1 ... done
$ docker ps -a
CONTAINER ID        IMAGE                         COMMAND                  CREATED             STATUS                        PORTS               NAMES
$ docker-compose up
```

ちなみに、WARNINGが発生してもボリュームは作成されている。

```
$ docker volume ls
DRIVER              VOLUME NAME
local               database_mysql
local               database_mysql_test
```

# `docker-compose up` 後の `Control+C` の挙動
前項を書いているときに、以下の4パターンに遭遇した。これは何故だ？

1. `Control+C` をすると `Abort` と表示され、コンテナが起動したままになる
2. `Control+C` をすると `Stopping` と表示され、コンテナが起動したままになる
3. `Control+C` をすると `Killing` と表示され、コンテナが停止する（前項の状況）
4. 2.または3.に加えて、停止したコンテナを削除できない

どうやらIssueらしい。
https://github.com/docker/compose/issues/3317

# 疑問点
[Mysqlデータベースはどこに保存されているのか](#mysql%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AF%E3%81%A9%E3%81%93%E3%81%AB%E4%BF%9D%E5%AD%98%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%AE%E3%81%8B)にて、ボリューム名が `database_mysql` となっているが、なぜこのような名前になっているのだろう。`database_` は自動で付与されるプリフィックス？