小ネタ集 〜GitHub ActionsでMySQLの初期データを投入するシェルスクリプトの実行! 編

ひとつのことを行おうとしたら、いろいろな技術要素の小ネタが集まることになった。

この記事は、5分LTネタを連投するイメージで書いていく。


最重要小ネタ

今回もっとも書き残したい小ネタNo.1は、「Windowsでシェルスクリプトを新規作成・記述し、Git等にプッシュするときは、文字コードと改行コードを見直しておくように」ということ。

▼Windowsのテキスト編集あるある

  • 文字コード:デフォルトでBOM付きUTF8の可能性が高い。
    →BOMのないUTF8で保存しなおそう。メモ帳の保存ダイアログから変えればOK。
  • 改行コード:デフォルトでCRLFの可能性が高い。
    →LFに直そう。テキストエディタの機能やIDEの機能で、改行コードを一括変換すればOK。

もしこれを直さず、BOM付きUTF8かつ改行コードがCRLFのシェルスクリプトファイルをプッシュし、GitHub Actionsの処理で実行させようとすると、シェルスクリプト実行時エラーでジョブが異常終了する。


それでは以下、タイトルの通り「GitHub ActionsでMySQLの初期データを投入するシェルスクリプトを実行させたときのこと。」に関わる小ネタを書き連ねていく。


MySQLの公式Dockerイメージ起動時、初期データを投入する方法

PostgreSQL公式、MySQL公式で足並みが揃えられ、共通のやり方になっている。

▼やり方。

  1. DBのコンテナに /docker-entrypoint-initdb.d ディレクトリをマウントする。
  2. .sh、.sql、.sql.gz 形式のファイルを用意し、上記 /docker-entrypoint-initdb.d ディレクトリに格納されるように設計する。

GitHub ActionsでもDocker×MySQL小ネタ(ひとつ前のセクションの件)はできるか

GitHubリポジトリにGitHub Actionsを定義しておき、プッシュのたびに自動テストが回る環境を作れたら安心だ。

この自動テストのため、DB起動時にデータを初期登録したいという需要がうまれる。

--

Docker×MySQL小ネタ(ひとつ前のセクションの件=DBに初期データを投入する件)をGitHub Actionsで適用している記事をあまり見かけなかったが、結論としては問題なく初期データ投入ができた。

あとで述べるが(というか冒頭のセクションの内容から感づいている読者もいらっしゃると思うが…)、私はスクリプトのバグ取りができるまで確信をもてず、やや狼狽しつつこの結論にたどり着いたのだけれども…。

MySQLのCreate User

アプリで使用するために、権限を縮小したroot以外の他ユーザアカウントを作りたいので、Create Userをコンテナの立ち上げと同時に実行したい、といった需要はあると思う。

それから、アプリ用のスキーマを生成するSQLなども。

前者、MySQLユーザアカウントを初期データとして投入する例では、SQLやシェルスクリプトに以下のように記述するだろう。 ※ファイル名は自由。

init.sqlの場合
------------
create user 'user_hoooo'@'%' identified by 'パスワードを平文で入れてしまう。';
grant select, insert, update, delete on \`testdatabase\`.* to 'user_hoooo'@'%';
init.shの場合
-----------
#! /bin/bash
mysql -u root -p${MYSQL_ROOT_PASSWORD} -e "create user 'user_hoooo'@'%' identified by '${PASSWORD_HOOOO}';";
mysql -u root -p${MYSQL_ROOT_PASSWORD} -e "grant select, insert, update, delete on \`testdatabase\`.* to 'user_hoooo'@'%';";

パスワードを平文で書かないシェルスクリプトの方がよさそう。

環境変数「MYSQL_ROOT_PASSWORD」「PASSWORD_HOOOO」は、GitHub ActionsのSecrets等に登録し、MySQLのDockerコンテナ立ち上げの際に連携しておく。あるいはもっと秘匿性の高いパスワード保管方法が求められるケースもあるかもしれない。

なお、「MYSQL_ROOT_PASSWORD」のほうはMySQLのコンテナに必須な環境変数でもある。

--

ところで。
MySQLは「ユーザ名+接続元ホスト」でユーザを一意に区別している。
ユーザ名が登録されていても、接続元ホストが登録されていなければコネクションを確立できない。

オンプレミスのMySQLの場合「root@localhost」はインストール時に作られるが、他クライアントから接続するための「root@%」(%はワイルドカード。ホスト名指定でもOK)は後から登録が必要な場合が多いと思う。

筆者は、他DBのやり方を知っていた作業をMySQLで実施しようとした際、この仕様に端を発する接続エラーで引っかかった経験がある。

👉DockerイメージのMySQLでは?
rootに関しては立ち上げの際に「root@%」が自動で登録されるので問題はない。

なおDockerは、他サービスからDBサービスに接続するにあたり「他サービス=別ホスト」と判断されるため、「@localhost」以外のユーザ作成は必須である。

GitHub ActionsとDocker Compose

workflow、Dokcerコマンドでいくか、Docker Composeコマンドでいくか。

GitHub Actionsで行う処理はworkflowに記述する。

workflowの詳細は上記公式ドキュメントが充実している。
具体的に記述する内容は、CLIベースでDockerを立ち上げる際に実行するコマンドを思い浮かべるといいだろう。

--

さて。
GitHub Actionsのworkflowの中で、Docker Composeにコンテナを生成・起動させることもできる。

念のため補足すると、Docker ComposeはDockerとセット扱いになりやすいが、必須というわけではない。ComposeがなくてもDockerは扱える。
そして、workflowをイチから記述する場合にDocker Composeを使うことはあまり思いつかないかもしれない。(やりたいことはすべて、workflowに直接書けばいいのだから。)

が、既にDocker Hubに公開しているイメージとセットで使ってもらうためのcompose.ymlを配布している場合などは、同じcompose.ymlが使えると効率がよいので、workflowからDocker Composeを呼び出し、コンテナ生成のやり方はそちらに任せたいという需要が発生する。

GitHub ActionsからのDocker Compose実行も、CLIベースでコマンドを実行するイメージでよい。

 workflow.yml - サービスhooooを起動する。
--------------
steps:
    - name: docker compose test hoooo
      working-directory: ./
      run: docker compose -f composeHoooo.yml run --rm hoooo

SQLファイルを用意するか、シェルスクリプトを用意するかによる体感の違い

脇道が続いたので本題に近い小ネタへ。

この次で、冒頭の最重要小ネタにたどり着く。

最重要小ネタ:Windowsでシェルスクリプトを書くときは。

シェルスクリプトをデバッグするレシピ

  翻译: