💬

Laradockで任意データベース作成・追加 - Laradock mysql - 少しdocker

2021/10/14に公開

経緯

LaradockでAPIサーバーとして使うLaravel 8.xを立ち上げるメモでは、一つのLaradock環境に複数のプロジェクトを立ち上げ、同時に開発可能な環境を構築しています。(主にこの辺の内容)

そして、他の関連記事でプロジェクトの追加を行っているのですが、一つ、スルーしている点があります。
利用するデータベースをプロジェクトごとに作成せずに共有しているという点です。

個人的には、phpMyAdminで追加しています。そう頻繁に行うことではないので、それで十分と思っていましたが、実際にやろうとすると少し面倒です。

Laradockたるもの、データベースの追加くらい用意してあるだろうと思って、laradock/mysql/*らへんを探ってみたら、、、
発見しました。

というわけで確認した内容を記事に残しておきます。

Laradockの任意データベース作成・追加方法

以下がすべてです。
laradock/mysql/docker-entrypoint-initdb.d/createdb.sql.example

このcreatedb.sql.exampleにたどり着けたものだけが、Laradockにおける複数データベース作成・追加の方法について知ることができるでしょう(たぶん)。

以降は、ほぼ、説明の翻訳のようなものですが、記載しておきます。

方法1:Laradock環境の新規構築

定番なやつですが、createdb.sql.examplecreatedb.sqlにリネームすることで有効になります。

以下のような記述例がありますので、これを基に任意のデータベース名に書き換えて記述するのがよいでしょう。

#CREATE DATABASE IF NOT EXISTS `dev_db_1` COLLATE 'utf8_general_ci' ;
#GRANT ALL ON `dev_db_1`.* TO 'default'@'%' ;

例えば、dev_app01というデータベースにするなら、データベース名2か所を書き換えます。

CREATE DATABASE IF NOT EXISTS `dev_app01` COLLATE 'utf8_general_ci' ;
GRANT ALL ON `dev_app01`.* TO 'default'@'%' ;

必要なら、ユーザーを変更しても良いでしょう。

ただし注意点があります。

このSQLスクリプトは、dockerコンテナが開始されたタイミングで、
MySQLのデータ管理ディレクトリが存在しない時にだけ、自動で実行されます。

つまり、Laradockで初めてdocker-compose up -d mysql的なことをした場合にのみ自動実行されます。
つまりつまり、追加はできません。

方法2:Laradock環境の再構築

自動実行したかったら、MySQLのデータ管理ディレクトリを消せ、そういうことです。もはや脅迫です。

MySQLのデータ管理ディレクトリとは、$DATA_PATH_HOST/mysqlのことです。
$DATA_PATH_HOSTは、laradock/.envに記載されています。

laradock/.env
# Choose storage path on your machine. For all storage systems
DATA_PATH_HOST=~/.laradock/data

Windowsの場合、C:\Users\ユーザー名\.laradock\dataです。

createdb.sqlを準備した上で、以下の手順を踏むとcreatedb.sqlに記載のとおりにデータベースが作成されます。

  1. laradockの停止(down)
    laradock> docker-compose down
    
  2. mysqlディレクトリ削除
    ~/.laradock/datamysqlを手動で削除、もしくはリネーム
    mysql.bakにリネームしておいて、不要になったら消す、とかでも良いかと。
  3. laradockの開始(up)
    環境に応じて以下のように。
    laradock> docker-compose up -d nginx mysql
    

これで、従来どおりのdefaultデータベースと、createdb.sqlに記載したデータベースが作成されます。

方法3:createdb.sqlを手動実行

もし、MySQLのデータ管理ディレクトリが存在していて、
それを消したくないと望むなら、手動で実行できます。

というわけで、データベースを追加したいなら、手動で追加しなさいということです。
createdb.sqlを用意することで記録として残せるのは利点ですが、結局手動です、手動なのです。

手動の実行方法も同スクリプトに書いてありますが、一応記載します。
mysqlが起動している状態で操作します。

  1. mysqlコンテナに接続
    laradock> docker-compose exec mysql bash
    
  2. スクリプト実行
    root@3b248e76c0ba:/# mysql -u root -p < /docker-entrypoint-initdb.d/createdb.sql
    Enter password:
    
    rootユーザーのパスワードの入力が求められます。
    laradock/.envMYSQL_ROOT_PASSWORDで設定しているパスワードを入力します。
  3. mysqlコンテナから切断
    root@3b248e76c0ba:/# exit
    

手動実行ということで面倒かと思いきや、これだけです。
CREATE DATABASEコマンドに、IF NOT EXISTSの記述があるため、同じ名前のデータベースがすでに存在する場合、該当のデータベースの作成は行われません。

データベースを追加したかったら、createdb.sqlにコマンドを追記してスクリプトを手動実行すれば良い、というお話でした。

補足:Dockerのmysqlについて少し

docker-entrypoint-initdb.dとは何か

/docker-entrypoint-initdb.d/createdb.sqlの実行は、どこの仕組みで、どのように行われるのか。
という点について蛇足補足します。

結論を先に書くと、
/docker-entrypoint-initdb.d/createdb.sqlの実行は、DockerのMySQLの公式イメージの仕組みにより、docker-entrypoint.shで行われます。

Laradockは、このようにPHP開発環境の構築に利用できるDockerイメージがあらかじめ選定されており、それらを簡単に利用できるような仕組みです。
Dockerあるいはdocker-composeの面では、いわばノウハウの宝庫です…、いや、宝庫は言い過ぎでかもしれません。洗練されてシンプルな組み合わせになっているので、掘り下げないと宝にはたどり着きません。言い換えるとするなら、ノウハウの宝庫の入口です(きっと)。
選定されているものを確認したり、Dockerfileの内容を確認するだけでも勉強になる、と思います。(docker-composeを組む際に、Laradockのdocker-compose.ymlを参考にさせていただいたりしました。)

docker-entrypoint-initdb.dを紐解いてみる

補足として言いたかったのは前項の点だけなのですが、せっかくなので紐解いてみます。

  1. docker-entrypoint-initdb.dという名前
    まず、docker-entrypoint-initdb.dという名前ですので、「dockerの仕組みに依存したもの」
    ということがすぐに分かります。

  2. laradock/mysql/Dockerfileの内容
    次に、laradock/mysql/Dockerfileの内容を確認すると、docker-entrypoint-initdb.dに対して何も記述がないことから、mysqlのDockerイメージの仕組みをそのまま利用しているということが分かります。

  3. 実際のDockerイメージ
    DockerfileのFROM mysql:${MYSQL_VERSION}という記述で、実際のDockerイメージが分かります。
    また、${MYSQL_VERSION}laradock/.envに記載のMYSQL_VERSION=latestが展開されます。
    というわけで、Laradockのmysqlのイメージは、mysql:latestが基になっていることが分かります。

  4. docker hub
    docker hubで確認してみます。
    https://hub.docker.com/_/mysql

  5. mysqlイメージのDockerfile
    docker hubのmysqlの画面の「Supported tags and respective Dockerfile links」のlatestをクリックすると、mysql:latestのDockerfileを閲覧できます。

    話の元になっているディレクトリのdocker-entrypoint-initdb.dという名称からアタリをつけて、ENTRYPOINTの設定を確認します。

    ENTRYPOINT ["docker-entrypoint.sh"]
    

    実行されているシェルのファイル名が特定できました。

  6. mysqlイメージのentrypoint
    docker-entrypoint.shを確認します。
    (latestのバージョンが8.0の場合)画面上部にmysql/8.0/Dockerfile.debianという表示中のパスの表記があるので、8.0のリンクをクリックしてファイル一覧を表示します。
    続いてdocker-entrypoint.shのリンクをクリックして開きます。

  7. docker-entrypoint.shの内容
    このシェルの内容を読み取るのは大変なのでポイントだけ抜き出します。

    ざっと眺めると、以下のような箇所があると思います。

    # there's no database, so it needs to be initialized
    if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
    

    「MySQLのデータ管理ディレクトリが存在しない時にだけ自動実行」という点は、ここの処理に則った仕組みということのようです。

    そして、上記のif文の中に、以下のような記述があります。

    docker_process_init_files /docker-entrypoint-initdb.d/*
    

    他にdocker-entrypoint-initdb.d内のファイルにアクセスしている箇所がないので、createdb.sqlはここで処理されるということになります。

    docker_process_init_filesを確認します。

    docker_process_init_files() {
        :
        *.sql)    mysql_note "$0: running $f"; docker_process_sql < "$f"; echo ;;
    

    docker-entrypoint-initdb.d内のファイルすべてをループで処理し、特定の拡張子のファイルに対して何らかの処理を行っているようです。
    createdb.sqlは、ファイルの内容が読み取られ、標準入力経由でdocker_process_sqlに渡されています。

    docker_process_sqlを確認します。

    # Execute sql script, passed via stdin
    # usage: docker_process_sql [--dont-use-mysql-root-password] [mysql-cli-args]
    #    ie: docker_process_sql --database=mydb <<<'INSERT ...'
    #    ie: docker_process_sql --dont-use-mysql-root-password --database=mydb <my-file.sql
    docker_process_sql() {
    

    処理の説明が記述されていました。ここで標準入力経由でSQLスクリプトを実行するようです。
    createdb.sqlはここで実行される、ということです。

laradockのdocker-compose.yml

ちなみに、laradockのdocker-compose.ymlの以下の記述も関連して重要な点ですので、追加で記載しておきます。ボリュームマウントしています、というお話です。

laradock/docker-compose.yml
### MySQL ################################################
    mysql:volumes:
        - ${DATA_PATH_HOST}/mysql:/var/lib/mysql
        - ${MYSQL_ENTRYPOINT_INITDB}:/docker-entrypoint-initdb.d
    :

補足:複数のLaradock

ついでにもう一つ補足です。
方法2で出てきた以下について。

laradock/.env
# Choose storage path on your machine. For all storage systems
DATA_PATH_HOST=~/.laradock/data

自身の開発環境では複数のLaradock環境を動かしています。
業務用Laradockと、検証用Laradock、という感じです。

Workspace的に、関係のないプロジェクトを混在させないようにしたい、ということでそうしているのですが、その際に行っているのが、DATA_PATH_HOSTの個別設定です。
例えば、以下のように分けておけば、検証用Laradockは細かいことを気にせずに気軽にスクラップ&ビルドやら再構築やらを行えます。

  • 業務用Laradock:DATA_PATH_HOST=~/.laradock/data1
  • 検証用Laradock:DATA_PATH_HOST=~/.laradock/data2

今回のcreatedb.sqlの説明を見て、検証用のLaradockであれば、予め余分にデータベースを作っておいて好きに切り替えるなんてのもありかな、などと考えています。
まぁ、php artisan migrate:fresh --seedすれば済む話なので、defaultデータベース1つで十分かもしれませんが、あるに越したことはない、ということで。

おわりに

今まで、Laradockでのデータベースの追加はphpMyAdminで行っていたのですが、今後はこの方法(方法3)で追加しようと思います。もっと早くちゃんと調べておくべきでした。

こんなところで。

Discussion