Go 言語で Docker を使うテストを書く時
日記。
Docker コンテナ内で立ち上げたサーバーに繋ぐテストを書く時の話。
テスト開始時にコンテナを立ち上げて、テストして、終了時に落とすみたいな奴。
コマンドや API を叩いてコンテナの実行が始まった直後に繋ぎに行くと、まだコンテナ内で
この時の対応策は色々あるだろうけども、1番安直な方法は恐らく「成功するまで
(コンテナ自体が不安定な場合は起動失敗してないか調べるのも必要そう)
この sleep の部分を「
https://github.com/oov/dockertest
コードの一部はこの記事を参考にさせてもらった。
パッケージを作る前に手作業で試してみた時点で「コンテナ内に
概ね、というのは PostgreSQL は
他のプログラムでも設定などによっては
環境変数
ところで、普段 Go 言語を使って遊んでいるのは自宅サーバの Ubuntu で作曲とかに使うマシンは Windows なんだけど、このテストを両方の環境で実行したら思っていたより速度差が大きかった。
CPU: Intel Atom D510 1.66GHz / Memory: 4GB / OS: Ubuntu 14.04
普段の環境で毎回1分近く掛かるのは結構辛いし、テスト開始時にコンテナを起動するか、名前をつけておいた起動済みコンテナを利用するのか自動で判断する仕組みが必要かもなぁ、と思ったのだった。
---- 追記 2015-11-20
起動済みのコンテナを再利用する仕組みを追加したところ、遅い環境でも1秒程度で終わるようになった。
名前しかチェックしていないのでイメージやパラメータが違う状態で起動しているのも利用できてしまったりするけど、厳密にやり過ぎても使いにくいかも知れないのでその辺りは緩めにしておくことにした。
同じパラメータで起動したい時は
Docker コンテナ内で立ち上げたサーバーに繋ぐテストを書く時の話。
テスト開始時にコンテナを立ち上げて、テストして、終了時に落とすみたいな奴。
コマンドや API を叩いてコンテナの実行が始まった直後に繋ぎに行くと、まだコンテナ内で
listen
が始まっていないのが原因で失敗する、ということがしばしば起こる。この時の対応策は色々あるだろうけども、1番安直な方法は恐らく「成功するまで
sleep
とリトライを繰り返す」という類のものだと思う。(コンテナ自体が不安定な場合は起動失敗してないか調べるのも必要そう)
この sleep の部分を「
netstat
の出力で listen
しているか調べる」という、これまた安直な方法で実現すれば、汎用的に使えるリトライ不要な手段になるのではないだろうか? と思い、少し作ってみることにした。https://github.com/oov/dockertest
コードの一部はこの記事を参考にさせてもらった。
パッケージを作る前に手作業で試してみた時点で「コンテナ内に
netstat
自体が存在しない」という理由で上手くいかず/proc/net/tcp などを見に行くようにアプローチを変えざるを得なかったものの、Docker Hub にあるオフィシャルの MySQL, PostgreSQL, Redis, MongoDB と、dnsmasq(andyshinn/dnsmasq) に繋ぐのを試した限りでは概ね成功した。概ね、というのは PostgreSQL は
listen
が始まった直後だと "the database system is starting up"
と言われて接続に失敗することがあり、結局リトライする処理が必要になったため。他のプログラムでも設定などによっては
listen
したあと更に準備時間が必要なケースもあるかも知れないので、結果的には思惑ほど全て上手くは行かなかったことになる。ちょっと残念。環境変数
DOCKER_HOST
の有無も考慮して動くようにしたおかげでテストに手を加えなくても Windows 環境でも Docker Quickstart Terminal とか boot2docker を経由してテストを実行できるし、パッケージとしては作ってよかったと思う。ところで、普段 Go 言語を使って遊んでいるのは自宅サーバの Ubuntu で作曲とかに使うマシンは Windows なんだけど、このテストを両方の環境で実行したら思っていたより速度差が大きかった。
CPU: Intel Atom D510 1.66GHz / Memory: 4GB / OS: Ubuntu 14.04
=== RUN Example_dnsmasq --- PASS: Example_dnsmasq (2.98s) === RUN Example_mongoDB --- PASS: Example_mongoDB (4.61s) === RUN Example_mySQL --- PASS: Example_mySQL (55.38s) === RUN Example_postgreSQL --- PASS: Example_postgreSQL (17.30s) === RUN Example_redis --- PASS: Example_redis (2.46s)CPU: Intel Core i7-4790K 4.00GHz / Memory: 32GB / OS: Windows 10
=== RUN Example_dnsmasq --- PASS: Example_dnsmasq (1.08s) === RUN Example_mongoDB --- PASS: Example_mongoDB (0.87s) === RUN Example_mySQL --- PASS: Example_mySQL (6.91s) === RUN Example_postgreSQL --- PASS: Example_postgreSQL (4.49s) === RUN Example_redis --- PASS: Example_redis (0.96s)
普段の環境で毎回1分近く掛かるのは結構辛いし、テスト開始時にコンテナを起動するか、名前をつけておいた起動済みコンテナを利用するのか自動で判断する仕組みが必要かもなぁ、と思ったのだった。
---- 追記 2015-11-20
起動済みのコンテナを再利用する仕組みを追加したところ、遅い環境でも1秒程度で終わるようになった。
名前しかチェックしていないのでイメージやパラメータが違う状態で起動しているのも利用できてしまったりするけど、厳密にやり過ぎても使いにくいかも知れないのでその辺りは緩めにしておくことにした。
同じパラメータで起動したい時は
Container.RunArgs
を利用するとコピペできて便利。