RailsアプリでCircleCI設定時にハマったこと

結論

Databaseコンテナの起動を dockerize を使って待ちましょう。

以下のような感じ。

     - run:
         name: 'wait for db'
         command: dockerize -wait tcp://localhost:3306 -timeout 1m

これの検証だけのために30回くらいビルドしたのは内緒🤬

[事の発端]自動テストでMySQL コンテナを利用しようと思った。

5.6を利用していたが、 rails db:create がCircleCI上で通らない。 でも何回かビルドしているとたまに通ったりする。(この時点でなにか非同期な処理によるものだと気づくべきだった。) (最初は、なぜか文字コードの問題だと思って戦っていた。)

エラーは以下のような感じ

#<Mysql2::Error::ConnectionError: Can't connect to MySQL server on '127.0.0.1' (111)>
Couldn't create database for {"adapter"=>"mysql2", "encoding"=>"utf8mb4", "charset"=>"utf8mb4", "collation"=>"utf8mb4_bin", "pool"=>5, "username"=>"root", "password"=>nil, "host"=>"127.0.0.1", "socket"=>"/tmp/mysql.sock", "database"=>"test"}, {:charset=>"utf8mb4", :collation=>"utf8mb4_bin"}
(If you set the charset manually, make sure you have a matching collation)
Created database 'test'

以下のようにして解決だと思った。(別に解決していない。)

config.yml

jobs:
  build:
    docker:
       - image: circleci/ruby:2.4.1-node-browsers 
         environment:
           RAILS_ENV: test
           DB_HOST: 127.0.0.1
           DB_USERNAME: 'root'
           DB_PASSWORD: ''
       - image: circleci/mysql:5.6
         environment:
           MYSQL_ALLOW_EMPTY_PASSWORD: yes

database.yml

efault: &default
  adapter: mysql2
  encoding: utf8mb4
  charset: utf8mb4
  collation: utf8mb4_bin
  pool: 5
  username: root
  password:
  host: localhost
  socket: /tmp/mysql.sock

test:
  <<: *default
  database: test
  username: <%= ENV['DB_USERNAME'] || 'root' %>
  password: <%= ENV['DB_PASSWORD'] || '' %>
  host: <%= ENV['DB_HOST'] || '127.0.0.1' %>

ポイント(だとおもっていたこと)

  • パスワードを設定しない場合は、config.ymlでmysqlコンテナに関して環境変数MYSQL_ALLOW_EMPTY_PASSWORDを設定すること。
  • database.ymlで encoding, charset, collation を設定すること。
    • この辺掘り下げてはいないが、collationを設定していないとコケる。
    • なんでだ。。。

エラー再発(当然である)

いろいろとググる。DB関係のブログを読んでいたらたまたまdockerizeについても言及してくれている方がいてこれかなと思うようになった。

dockerコンテナの立ち上げを待つ必要がある?(これが結論)

dockerizeを利用することで解決可能っぽい。

     - run:
         name: 'wait for db'
         command: dockerize -wait tcp://localhost:3306 -timeout 1m

ぶつかっていた問題は文字コード云々ではなく、dockerコンテナの起動を待つことだった。そりゃ起動していないコンテナに命令は出せないよね。。。。精進します。

参考記事