docker-composeでno declaration was foundというエラーに遭遇

Docker上にRailsが動く環境を構築してあれやこれやと試していたらrailsが`db:migrate`しろ！といったので実行したら不思議なエラーに遭遇したのでメモしておく。


# TL;DR

エラー内容は非常にシンプルなものを返していて、volumesセクションないぞ！とかMySQLに接続できねえぞ！とかって怒られている。

ほんの少し前まで接続できたのに何故だろうか？直前でどんな変更したっけなーと記憶を探りながら格闘したがよくわからんので寝て仕事してジョギングしてググったりしていろいろ試したらとりあえず直った。

どなたか原因を推測出来る人か説明されているサイトを知っている人がいたら教えてくれると嬉しいです。
正直直ったけどまだ原因がきちんとわかってなくて不可解な気持ちなので…。

# 環境

- Mac OS Siera ver.10.12.5
- mysql 5.7.18
- Docker version 17.06.0-ce
    - DockerでWebコンテナにRails、DBコンテナにMySQLを作ってる

# エラー

エラーの種類と試した経緯は↓

- volumesを追加したあとでエラーになったので追加前の状態にファイルなどを巻き戻して起動するかチェックしようとしたらエラー

```bash

$ docker-compose up
ERROR: Named volume "db:/var/lib/mysql:rw" is used in service "[コンテナ名(DB)]" but no declaration was found in the volumes section.
```

- ファイルなどは全てエラー前のものに戻しているのでMySQLの状態がおかしくなってしまっているのかもしれないと思い、一旦`docker-compose run [コンテナ名(Web)] rails db:migrate:reset`してまっさらな状態からやり直そうと思ったらエラー

```bash

docker-compose run [コンテナ名(Web)] rails db:migrate                                                                                                                           [07 19 00:56:29]
Starting [コンテナ名(DB)] ... done
rails aborted!
Mysql2::Error: Host '172.22.0.4' is not allowed to connect to this MySQL server
/usr/local/bundle/gems/mysql2-0.4.7/lib/mysql2/client.rb:89:in `connect'
/usr/local/bundle/gems/mysql2-0.4.7/lib/mysql2/client.rb:89:in `initialize'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/connection_adapters/mysql2_adapter.rb:21:in `new'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/connection_adapters/mysql2_adapter.rb:21:in `mysql2_connection'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:759:in `new_connection'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:803:in `checkout_new_connection'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:782:in `try_to_checkout_new_connection'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:743:in `acquire_connection'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:500:in `checkout'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:374:in `connection'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:931:in `retrieve_connection'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/connection_handling.rb:116:in `retrieve_connection'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/connection_handling.rb:88:in `connection'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/schema_migration.rb:20:in `table_exists?'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/schema_migration.rb:24:in `create_table'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/migration.rb:1125:in `initialize'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/migration.rb:1007:in `new'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/migration.rb:1007:in `up'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/migration.rb:985:in `migrate'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/tasks/database_tasks.rb:171:in `migrate'
/usr/local/bundle/gems/activerecord-5.1.2/lib/active_record/railties/databases.rake:58:in `block (2 levels) in <top (required)>'
/usr/local/bundle/gems/railties-5.1.2/lib/rails/commands/rake/rake_command.rb:21:in `block in perform'
/usr/local/bundle/gems/railties-5.1.2/lib/rails/commands/rake/rake_command.rb:18:in `perform'
/usr/local/bundle/gems/railties-5.1.2/lib/rails/command.rb:46:in `invoke'
/usr/local/bundle/gems/railties-5.1.2/lib/rails/commands.rb:16:in `<top (required)>'
bin/rails:4:in `require'
bin/rails:4:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
```

## 解決:

原因は今持ってはっきりとはまだわかっていない。
`docker-compose.yml`の`volumes`を正しいパスに修正&追加したら直った。

## 解説兼推測:

原因の発端となったのは`docker-compose.yml`の`sevices`セクションにMySQLの設定を行っていたあとに発生した(そのあとも実はちょっとだけModel追加したりゴニョゴニョしてたが一旦全て巻き戻してた)。

MySQLのデータを永続的にするには`volumes:-data:/var/lib/mysql`するとよいぞ！と参考にみていたサイトで書かれていたので同じように書いたところエラーが出るようになったのかな？と推測。

とりあえず原因がわからなすぎたのでエラーメッセージ+Dockerという単語で検索してみた。

「docker not allowed to connect to this MySQL」でググったら
[Host '172.18.0.1' is not allowed to connect to this MySQL server #275](https://github.com/docker-library/mysql/issues/275)というissueも発見した。
こちらは解決そのものには直結しなかったけどこの値がきちんと例として上げられているような値になっているか？という確認を行うのに参考になった。

「docker but no declaration was found in the volumes section.」でググったところ
[docker-compose: no declaration was found in the volumes section #67](https://github.com/ClusterHQ/dvol/issues/67)というissueを発見。
最終的にこのissueが問題解決に繋がったかなとみている。

どうも似たような問題に遭遇してそうだったのでアドバイスしているコメントを読んだり、Google翻訳かけたりしていたら

> ERROR: Named volume "data:/cjworkbench:rw" is used in service "web" but no declaration was found in the volumes section.
use ./data instead of data and make sure directory ./data exists.

おめえの指定してる`volumes`の指定おかしくね？的な内容を発見。
これが原因なのか？と思いつつ、間違っている箇所を1つずつ修正していかないと本丸にたどり着けないなと思ったので`volumes`の指定を修正。

これで直るとは思わないけど一応`docker-compose down`して`docker-compose up -d`してみるかーと試したら正常に起動してしまった。

一応URLを叩いて確認したところ無事Railsの画面が表示されました…という次第です。

### エラーの推測

きちんと調べられていないのだけどdocker-compse.ymlの指定が間違っていたことで変な状態でMySQLのデータが永続化されてしまっていたのかな？と思ってる。

指定前のデフォルトがなにかしらの理由で書き換わるとかされてしまい、そのデータが残り続けたために起こったのかなと思ってるが正直よくわからない。

Docker公式のdocker-compose.ymlの内容も一応確認していたが問題なさそうだと思ってみていたがどこかをすっ飛ばしてしまったのかもしれない。
あとでもう一度読み直しておこうと思う、そうすればある程度確度の高い推測か結果そのものを得られそう。

## まとめ

時間をおいて再チャレンジ、大事。
とりあえずこれで開発できる状態にまでは戻った。
途中面倒くさすぎてRailsじゃなくてGoでAPI鯖書いてやろうかと思ったけどRails関係なかったし、諦めずに調べて良かった…かもしれない。