2014-08-21

気づいたらいつの間にか Docker Official な MySQL イメージ が公開されていたので、ちょうどとある製品の検証目的で使い捨てられる MySQL の環境が欲しかったついでに試してみたところ、ちょっとハマって数時間を無駄にしてしまったことにカッとして書き殴ったメモ。

(photo by Mark Interrante)

達成したいこと

達成したかったことは以下のとおり。

  • お手軽にポイ捨てできる MySQL 環境を構築・用意したい
  • Dockerfile をシコシコつくるのは面倒だったので、既存の Docker イメージを利用したい
  • boot2docker はあんまりいい思い出がなかったので、Vagrant で構築した VM 上に Docker 環境を構築したい

やろうとしたこと

やろうとしたことの具体的な手順は以下のとおり。

  1. Ubuntu 14.04 の VM 環境を Vagrant で用意する
  2. 上記の VM 環境上に Docker をインストールする
  3. MySQL な Docker イメージを pull する
  4. pull した Docker イメージを run する

実際はどうだったのか?

1. Ubuntu 14.04 な VM 環境を Vagrant で用意する

Ubuntu 14.04 の daily Cloud Image を利用して vagrant init && vagrant up してみた。

Docker をインストール & docker pull するあたりまではうまくいったものの、MySQL イメージを docker run するところで、mysqld が起動しないという問題に遭遇してしまった。

以前、別件で orchardup/mysql の Docker イメージを使ったときはこんな問題は起こらなかったのになあ、と思いつつ docker logs container-id としてコンテナのログを確認してみると、

2014-08-20 16:31:09 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2014-08-20 16:31:10 1 [Warning] Buffered warning: Performance schema disabled (reason: init failed).

2014-08-20 16:31:10 1 [Note] Plugin 'FEDERATED' is disabled.
2014-08-20 16:31:11 1 [Note] InnoDB: Using atomics to ref count buffer pool pages
2014-08-20 16:31:11 1 [Note] InnoDB: The InnoDB memory heap is disabled
2014-08-20 16:31:11 1 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2014-08-20 16:31:11 1 [Note] InnoDB: Memory barrier is not used
2014-08-20 16:31:11 1 [Note] InnoDB: Compressed tables use zlib 1.2.3
2014-08-20 16:31:11 1 [Note] InnoDB: Using Linux native AIO
2014-08-20 16:31:11 1 [Note] InnoDB: Not using CPU crc32 instructions

…ログはここで途切れている。

2014-08-20 16:31:10 1 [Warning] Buffered warning: Performance schema disabled (reason: init failed).

の行が怪しいなあ、ということでこのエラーメッセージでぐぐってみると、Oracle のページ が引っかかった。

当該ページにある

you may have specified other Performance Schema variables with values too large for memory allocation to succeed.

を読む限り、「これメモリが足りないんじゃね?」疑惑が湧いてきたので、Vagrantfile を以下のようにいじいじして、メモリサイズを 1GB にしてみたら、ちゃんと起動するようになった。めでたしめでたし。

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  # (省略)

  config.vm.provider "virtualbox" do |vb|
    vb.customize [ "modifyvm", :id, "--memory", 1024 ]
  end

  # (省略)
end

2. 上記の VM 環境上に Docker をインストールする

apt-get install docker.io でインストールできる Docker は 0.9 だった。

せっかくなので新しいバージョンを使ってみたいので、

curl -s https://get.docker.io/ubuntu/ | sh

として Ubuntu 向け最新のバージョンをインストールするのであった。

3. MySQL な Docker イメージを pull する

以前使っていた orchardup/mysql は GitHub の README を見るとオワコン宣言されていたので、Docker official らしい Docker イメージに乗り換えるのであった。

4. pull した Docker イメージを run する

とりあえず

docker run \
  --name hogehoge \
  -e MYSQL_ROOT_PASSWORD=hogehoge_password \
  -d \
  mysql

で mysql イメージのコンテナを立ち上げて、Docker コンテナをホストしている Ubuntu 上の MySQL CLI で

mysql -u root -phogehoge_password -h 127.0.0.1

としてみたんだけど、

Can't connect to MySQL server on '127.0.0.1' (111)

などと悲しいことを仰る MySQL CLI さんに、僕は涙を浮かべずにはいられなかった。

ps コマンドでコンテナ上の mysqld が稼動していることは確認できたものの、それ以上のことはわからず試行錯誤したりいろいろぐぐったりしているうちに、「これコンテナのポートが開いてないんじゃね?」疑惑が湧いてきて Difference between “expose” and “publish” in docker のページにたどり着いた。

当該 Stackoverflow のページの回答をかいつまんで説明すると、

  • Dockerfile にて EXPOSE でポート番号を設定すると、コンテナ間でポートを通じた通信ができるようになる
    • コンテナ間の通信をしたい場合は、これを設定すべき
  • Dockerfile での EXPOSE のポート番号指定に加えて、 docker run する際の -p hostPort:containerPort を指定すると、 コンテナ側のポート containerPort をホストのポート hostPort でパブリッシュする
    • コンテナ間だけでなく、Docker の外の世界と通信したい場合は、 -p も設定すべき

ということになる。そんなわけで、

docker run \
  -p 3306:3306 \
  --name hogehoge \
  -e MYSQL_ROOT_PASSWORD=hogehoge_password \
  -d \
  mysql

としてコンテナを立ち上げてみたところ、ようやく MySQL CLI からコンテナ上の mysqld にご挨拶をするハッピーエンディングを迎えることができたのであった。

まとめ

Docker ネタのブログエントリって、たいてい Dockerfile の手組みから始まる系のやつが多い印象なんだけど、既存の Docker イメージを活用するカジュアル利用的なブログエントリももうちょっと増えてもいいと思う。

おまけ

できあがった Vagrantfile はこちら。