&を実行すると以下のような出力がありました。(GPL)一番下にソケットができた旨の出力がありますよね。connections)ソケットができたので接続可能になったということのようです。)にはなにが代入されたんでしょうか?実際出力させてみると...mysqlえ?これだけ?もっとゴイスーな数値が入ったりしないの?変数にいれる必要あるの?しかしこれはこの後に出てくる更に難解な変数の序章でした...。1fiさてこの箇所では何をやっているんでしょう?この部分から察するに何かを30回試行するみたいですね。doコマンドのうまい使い方さて問題はお次の箇所。breakfi${mysql[@]}←ファッ?なにこれ?変数展開ということはギリ理解できるが[@]ってなんやねん...難解。調べた、ググった、全然[@]の情報がヒットしない...。記号って検索しにくいな...。いうわけで自分でシェルスクリプトを書いて挙動を確かめました。結論から言うと[@]は「引数を伴った変数展開」を表すようです。"${list}"はlsが出力されました。オプションは出力されないんですね。"${list[@]}"以下のように出力されます。-lオプションも出力されていますね。)の部分で変数mysqlには”mysql”が格納されました。)でくくるのは「サブシェルでのコマンド実行」であり、「実行結果」を表すものではなかったのです。"${list}"以下のように出力されます。「実行結果」ですよね。-urootが格納され、オプションも出力するときには"${mysql[@]}"という書き方をするということのようです。確認用SQL文さてハマりついでにもうひとハマり。簡単そうに見えるけど...。こんなん必要なの?結論から言うとこれSQL文なんですよ...。こんなんあるんですね。このセレクト文では整数値の1が取得できます。1が返ってくることでmysqldにつながったことが明確にわかるのです。データベースも何もない状態ですから、mysqldがまっさらな状態でも返せるSQL文ということなんでしょうね。接続確認の意味合いのようですよ。thenは真となり、breakするわけですね。シェルスクリプトは0が真になるので若干ややこしす。1fi$iが0になりますからこの部分が真になり、接続できなかった旨を表示して終了します。page/FCTY/'fi$MYSQL_INITDB_SKIP_TZINFOが空なら(ーz)実行するようになっていますね。データベースに、タイムゾーンテーブルをロードするプログラムだそうです。databaseという世界各地域の標準時データ(別名zoneinfo)があるそうで、LinuxやMacで利用されています。このデータがあれば全世界の時刻を扱うことができるということですね。databaseをデータベースに取り込むためのプログラムということのようです。mysql_tzinfo_to_sqlをパイプでsedにつないでいますが、この箇所の処理はどうも不具合に対する処理のようです。コメントにもあるとおりhttps://bugs.mysql.com/bug.php?id=20545を確認してみてください。pageという記述がなにやら悪さをするそうで、それを書き換えているということです。page');こんなふうに書き換えているわけですね。'FCTY');正直なにがダメなのかよくわからないです...ごめんなさい。$MYSQL_ROOT_PASSWORD"fiここはすんなりわかりました。MYSQL_RANDOM_ROOT_PASSWORDを指定している場合、ランダムでパスワードをつくってくれます。その処理がここで行われています。ここでは32文字のパスワードを生成しています。ちなみにこんな感じのパスワードになります。;EOSQLさてこの部分ではいくつかのSQLをクライアントを通して実行しています。バイナリログの無効化まずはこの部分。@@SESSION.SQL_LOG_BIN=0;SESSION.SQL_LOG_BINはバイナリログにログを残すかどうかの設定です。バイナリログというのは、テーブルやデータへの操作、変更などがイベントとして残るそうです。いくつかのデータリカバリ処理にはこのバイナリログが必要になる場合があるそうです。この場合バイナリログを取らない設定にしているということですね。調べたところ、どうやらレプリケーションをもちいるときにこのバイナリログが悪さをする可能性があるみたいです。レプリケーションとは負荷分散などの目的の為にデータを複数複製する機能です。マスターデータがあってスレーブをたくさん持てるので、スレーブにアクセスしてもらうことで一極集中せずに済みます。マスターでユーザを増やした場合などにバイナリログが有効になっていると、スレーブで必要ないマスターのユーザ情報が伝わってしまい、なにやら不吉なこと(スレーブが止まるとか)が起きるらしいです。これ以降でユーザ操作をおこなっているので必要な設定なのではないかと思います。;ここはそれほど難しくないですね。ユーザを全消ししてrootユーザを作っています。rootユーザのパスワードにはMYSQL_ROOT_PASSWORDが当てられていますね。あとはGRANTでrootにすべての権限を与え、テストデータベースを削除して、権限を更新しています。)fiここでは変数mysqlにrootパスワードを追加しています。先ほどrootを作っていますから、これでパスワードをつかってログインできるようになります。)fiここでデータベースを作成しています。MYSQL_DATABASEがデータベース名になります。EXISTSは「もしこの名前のデータベースがなかったら作る」という意味です。このSQLを${mysql[@]}にパイプで渡して実行、その後に変数mysqlにデータベース名を足しています。いままでの処理で変数mysqlは以下のようになっているはずです。作られたデータベースにログインする為のコマンドに仕上げられていますね。"${mysql[@]}"fi公式のMySQLではroot以外にユーザを作ることも可能です。MYSQL_PASSWORDを指定しているとrootではなくこのユーザでログインすることもできるようになります。作ったデータベースで全権をユーザに与える処理がされていますね。esacechodoneちょっと複雑そうにみえますが、ここでは自作のshやsqlファイルでデータベースを初期化できるようにしてあります。/docker-entrypoint-initdb.d/にsh、sql、sql.gzに該当するファイルがあるとそれらを実行してくれる様になっています。ここでも"${mysql[@]}"が大活躍です。何らかのデータを起動時に入れてしまいたい場合はsql等でぶっこむことが可能になっています。具体的にはdocker-entrypoint-initdb.dをデータボリューム等でバインドしてファイルを突っ込む方法を取るかと思います。run時にMYSQL_ONETIME_PASSWORDを有効にしていた場合の処理です。EXPIREはパスワードに期限を付けます。次回ログインには別なパスワードを設定する必要があります。up.'echoおぼえていますでしょうか?以下の部分でmysqldのプロセスID取得していましたよね。&pid="$!"変数pidをつかってmysqldを終了しようとしています。"$pid"のTERMシグナルはプロセスを正常終了させる為のシグナルです。条件には!が付いているので、「正常終了できなかった時」という意味デス。"$pid"のwaitはプロセスが終了するのを待つコマンドです。これも!が付いているので、「正常に待てなかった時」という意味になるかと思います。正常終了できないか、プロセスを終了させられない場合には失敗したと判断してエラーをだしてセットアップを終了するようにしています。up.'echoを出力してセットアップが正常に終わったことを表示します。"$@"さて今までは初回起動時にデータベースを作る為の処理でした。2回目以降の起動はデータベースがすでに作られているはずなので、セットアップ処理はされません。"$@"がありますが、これは初回起動でも2回目の起動でも、mysqldを起動させるコマンドです。DockerfileのCMDが引数になりますので、”mysqld”が実行されるわけですね。してMySQLコンテナは起動するわけです。まとめ読んで理解するのは大変ですね。コードを書くより人のコードを読む方が難しく感じます。時間はかかりましたが、ある程度理解できてよかったです。こんな記事が役に立つかどうかはわかりませんが、暇つぶしにはなるかもしれません。mino長年働いていた会社をリストラされてしまったおっさん。なにを思ったか未経験のプログラミングで再起を図ろうとする。プログラミングを勉強していく上で苦しんだこと、ハマったことを中心に記事を書きます。