LoginSignup
19
5

More than 1 year has passed since last update.

GitHub ActionsでMySQL8系の認証方法を変更してRailsから接続する方法

Last updated at Posted at 2021-02-14

MySQL8では5系から比べると大幅にパフォーマンスが改善されたり、Window関数が使えるようになるなど様々な改善がされています。
ただ、デフォルトの認証方式がcaching_sha2_passwordになったため、この認証方式に対応していないRailsからはデフォルト設定のまま接続することができなくなりました。

何も対応せずにRailsからDB接続しようとすると下記のようなエラーが発生します。

Mysql2::Error::ConnectionError: Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory

これを解消するにはMySQLの認証方式を以前のmysql_native_passwordに変更すれば良いです。

開発環境はdocker-composeを使っている場合は下記のようにcommandに--default-authentication-plugin=mysql_native_passwordを記載すれば変更できます。
オプションについてはMySQLの公式ページをご覧ください。

docker-compose.yml
    db:
      image: mysql:8.0.23
      command: --default-authentication-plugin=mysql_native_password
      environment:
        MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
      volumes:
        - ./tmp/mysql:/var/lib/mysql

ここまではググれば関連記事が大量に出てきたのですが、GitHub ActionsでRailsとMySQL8を接続させる場合には同様のやり方では上手くいかず、ググってもピンポイントな記事が見つからなかったのでこの記事を書くことにしました。

GitHub Actionsではどうなるのか?

GitHub ActionsでRSpecを動かす場合を考えます。

docker-composeと同じノリで書くと下記のようになります。
リファレンスを見ると、commandはなくて代わりにoptionsというものがあるのでそちらで指定してみます。

.github/workflows/ci.yml
name: CI

on: pull_request

jobs:
  rspec:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    env:
      RAILS_ENV: test
      DB_HOST: 127.0.0.1
      DB_PORT: 33060
    services:
      db:
        image: mysql:8.0.23
        options: --default-authentication-plugin=mysql_native_password
        ports:
          - 33060:3306
        env:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
          BIND-ADDRESS: 0.0.0.0
    steps:
      - uses: actions/checkout@v2.3.4
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1.64.1
        with:
          ruby-version: 3.0.0
          bundler-cache: true
      - name: bundle install
        run: |
          gem install bundler
          bundle install --jobs 4 --retry 3 --path vendor/bundle
      - name: migration
        run: |
          bundle exec rails db:create
          bundle exec rails db:test:prepare
      - name: run rspec
        run: bundle exec rspec

これを実行すると下記のエラーが発生します。

  /usr/bin/docker create --name 79005cee16264952b54833428bec9736_mysql8023_27d475 --label 442333 --network github_network_cc57110ece5a47fe9679c23b82763cab --network-alias db -p 33060:3306 --default-authentication-plugin=mysql_native_password -e "MYSQL_USER=root" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" -e "BIND-ADDRESS=0.0.0.0" -e GITHUB_ACTIONS=true -e CI=true mysql:8.0.23
  unknown flag: --default-authentication-plugin
  See 'docker create --help'.
  Error: Exit code 125 returned from process: file name '/usr/bin/docker', arguments 'create --name 79005cee16264952b54833428bec9736_mysql8023_27d475 --label 442333 --network github_network_cc57110ece5a47fe9679c23b82763cab --network-alias db -p 33060:3306 --default-authentication-plugin=mysql_native_password -e "MYSQL_USER=root" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" -e "BIND-ADDRESS=0.0.0.0" -e GITHUB_ACTIONS=true -e CI=true mysql:8.0.23'.

unknown flag: --default-authentication-pluginと言っています。--default-authentication-pluginがわからないみたいですね。

エラーメッセージの直前に実行されたコマンドがあるので見てみると、--default-authentication-pluginがmysqlのオプションではなく、dockerのオプションに指定されていることがわかります(リファレンスにもきちんとDockerのオプションと書いてあります)。
dockerコマンドに対して指定してしまっているので、unknownと言われているんですね。

改めてリファレンスを読んでもimage(mysql)に対してオプションを指定する方法は現時点ではないようです。

では、どうするか?
実はMySQLにはもう1つ設定値を外部から指定する方法があります。

MySQLの設定ファイルを使う

MySQLの設定ファイルmy.confを見てみると下記のように外部ファイルを読み込む記載があります。

/etc/mysql/my.cnf
# Custom config should go here
!includedir /etc/mysql/conf.d/

そしてGithub Actionsのリファレンスをみると、serviceにvolumesを指定することでファイルを共有できそうです。

これらの仕組みを使います。

まず追加する設定ファイルを用意します。
my.cnfファイルの書き方は下記をご覧ください。
https://dev.mysql.com/doc/refman/5.6/ja/option-files.html

mysqlconf.d/custom.cnf
[mysqld]
default_authentication_plugin=mysql_native_password

次にvolumesを指定します。
(host側もmysql/conf.dにしようとしたのですが、Github Actionsではhost側に/が含まれていると正しく実行できなかったので下記のような1階層のディレクトリにしました)

.github/workflows/ci.yml
    services:
      db:
        image: mysql:8.0.23
-       options: --default-authentication-plugin=mysql_native_password
+       volumes:
+         - mysqlconf.d:/etc/mysql/conf.d
        ports:
          - 33060:3306
        env:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
          BIND-ADDRESS: 0.0.0.0

これらの修正を行うと先ほど失敗していたMySQL Serviceも生成され、DB接続もできるようになりました。

...
Starting db service container

...

/usr/bin/docker create --name c32ec17009124eab8461d555fc75a8e5_mysql8023_2e2c19 --label 442333 --network github_network_d9a9770fae8e43fcb9fc76e256a37c24 --network-alias db -p 33060:3306  -e "MYSQL_USER=root" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" -e "BIND-ADDRESS=0.0.0.0" -e GITHUB_ACTIONS=true -e CI=true -v "mysqlconf.d":"/etc/mysql/conf.d" mysql:8.0.23

...

Run bundle exec rails db:create
  bundle exec rails db:create
  bundle exec rails db:test:prepare
  shell: /bin/bash -e {0}
  env:
    RAILS_ENV: test
    DB_HOST: 127.0.0.1
    DB_PORT: 33060
Created database 'app_test'

...
19
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
5