😸

DockerのMySQLでprisma migrate devが成功する方法

2024/05/05に公開

Docker 上の MySQL に接続している Node.js サーバーで Prisma を動かしている。
npx prisma migrate dev を実行すると、以下のようなエラーが起きた。

Error: P3014

Prisma Migrate could not create the shadow database. Please make sure the database user has permission to create databases. Read more about the shadow database (and workarounds) at https://pris.ly/d/migrate-shadow

Original error: Error code: P1010

User `admin` was denied access on the database `XXXX`
version: '3'

services:
  mysql:
    image: mysql:8.0
    container_name: my_product
    command: mysqld --default-authentication-plugin=mysql_native_password --sql-mode=NO_ENGINE_SUBSTITUTION
    ports:
      - "3308:3308"
    volumes:
      - - db-store:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${ROOT_PASS}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER} # admin
      MYSQL_PASSWORD: ${DB_PASS}
      MYSQL_TCP_PORT: 3308

volumes:
  db-store:

root とは別に admin というユーザーを作り、接続している。
権限を確認。

mysql> show grants for admin;
+------------------------------------------------------------+
| Grants for admin@%                                         |
+------------------------------------------------------------+
| GRANT USAGE ON *.* TO `admin`@`%`                          |
| GRANT ALL PRIVILEGES ON `XXXX`.* TO `admin`@`%` |
+------------------------------------------------------------+

全件あるから問題なさそう...だが違う。
Prisma Migrateのshadow databaseの機能は、新しいデータベースを作成する権限が必要。公式

手作業なら

docker container exec -it mysql mysql -h mysql -u root -p でルートユーザーとしてログイン
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' WITH GRANT OPTION; を実行して権限付与
FLUSH PRIVILEGES; を実行して権限をリロード
SHOW GRANTS FOR 'admin'; を実行して変更されたことを確認

でも、いちいち立ち上げるたびにやるのは面倒...

なので、コンテナ初回起動時にスクリプトを実行させる

version: '3'

services:
  mysql:
    image: mysql:8.0
    container_name: my_product
    command: mysqld --default-authentication-plugin=mysql_native_password --sql-mode=NO_ENGINE_SUBSTITUTION
    ports:
      - "3308:3308"
    volumes:
      - - db-store:/var/lib/mysql
      # ここを追加
      - ./mysql-init:/docker-entrypoint-initdb.d
    environment:
      MYSQL_ROOT_PASSWORD: ${ROOT_PASS}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER} # admin
      MYSQL_PASSWORD: ${DB_PASS}
      MYSQL_TCP_PORT: 3308

volumes:
  db-store:

docker-compose.yml と同じ階層に mysql-init ディレクターを作成し, init.sql を作成

mkdir mysql-init
cd mysql-init
touch init.sql
GRANT CREATE, ALTER, DROP, REFERENCES ON *.* to 'admin'@'%';
FLUSH PRIVILEGES;

再度立ち上げ

docker-compose -p my_product up -d

node.js コンテナ内で再度 npx prisma migrate dev 実行

できた!

参考

https://polidog.jp/2023/05/03/prisma-mysql/

https://zenn.dev/ms_ddd/articles/69d504a8505527

https://laboratory.kazuuu.net/connect-to-mysql-server-from-within-a-mysql-container-with-docker/

https://zenn.dev/re24_1986/articles/978801ae092498

Discussion