sky’s 雑記

主にAndroidとサーバーサイドの技術について記事を書きます

MySQLコンテナのready for connectionsを保証する

マイグレーションなどアプリケーションからMySQLを操作する場合にMySQLの起動を保証する方法についてです。

概要

docker exec db mysql -u${DB_USER} -p${DB_PASSWORD}MySQLのready for connectionsを保証できます。

      - name: wait for connections ready
        env:
          DB_USER: ${{ secrets.DB_USER }}
          DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
        run: |
          while ! docker exec db mysql -u${DB_USER} -p${DB_PASSWORD}; do
            sleep 1s
          done
        shell: bash

背景

MySQLとアプリケーションを別々のコンテナで管理しておりMySQL起動後にアプリケーションからDBを操作するケースで、 以下のようにMySQL起動後にアプリケーションからDBを操作しようとすると SQLSTATE[HY000] [2002] Connection refused となり失敗する。

      - name: launch mysql
        run: docker run -d -p 3306:3306 --name=db mysql/mysql-server:8.0

      - name: setup db
        run: docker run db php artisan migrate

これはMysqlを起動して即時ready for connectionsにならないことが原因なので、上記の処理を行うためにはsetup dbの前段でMySQLがready for connectionsになっていることを保証する必要がある。

docker-composeを利用するのが一番手っ取り早そうだったが、Github-hostedなubuntuにdocker-composeコマンドが存在せずdockerコマンドのみインストールされていたのでdockerコマンドで実現することを考える。

方法

うまくいく方法

1. mysql -u${DB_USER} -p${DB_PASSWORD}

冒頭で記載した方法。 接続に成功する場合docker execの終了コードが0になるのでこの方法で判定できる。

うまくいかない方法

1. docker inspect -f {{.State.Running}} db

コンテナのステータスがRunningであればsetup dbを実行する方法。 コンテナの起動とMySQLのready for connectionsは関係がないのでうまくいかない。 コンテナのステータスがRunningになるほうが早くConnection refusedになる。

2. mysqladmin ping

mysqladminのpingコマンドを利用するネットで検索するとよく見つかる方法、healthcheckでこのコマンドを実行しているdocker-composeもあるが今回のユースケースではうまくいかない。 公式[1]に記載があるとおりAccess Deniedでも0が返却されるので実行結果のstatusを見るだけでは100%ready for connectionsを保証することはできない。

Check whether the server is available. The return status from mysqladmin is 0 if the server is running, 1 if it is not. This is 0 even in case of an error such as Access denied, because this means that the server is running but refused the connection, which is different from the server not running.

未確認な方法

1. 実行ログを確認する

Qiitaで投稿されていた方法[2]で未確認だが雰囲気うまくいきそう。

参照

[1] MySQL :: MySQL 8.0 Reference Manual :: 4.5.2 mysqladmin — A MySQL Server Administration Program

[2] docker-compose を CI で実行するとき, MySQL の起動完了まで確実に待つ - Qiita