2014年4月26日土曜日

Golang Cafe #26を開催しました。

Golang Cafe #26を開催しました。

今回からdockerソースコードを読み進めることになりましたので、”当然”main()から読み進めるのが妥当だろうということでmain()が書かれているdocker/docker.goから読み始めました。

流れとしては、最初に".dockerinit"という文字列が含まれているとinit modeでの起動ということで、sysinit.Sysinit()が呼び出されます。パスに".dockerinit"が含まれる時ということなので、docker自身が隠しディレクトリを作る事があるのだと思いますが、sysinitは少し重たそうだったので、少しだけ見て、先に進むことにしました。sysinitパッケージは後日に回します。

dockerは引数、オプションを扱うflagパッケージを自作しているようで、別名でflagパッケージを定義してありました。

flag "github.com/dotcloud/docker/pkg/mflag"

使っている所をみると、オプションを配列で指定することができるようにしてあるだけのようにも見えますが、とりあえずは最初の起動の処理をみるということにして、flagも存在だけのチェックで終わっています。

それぞれの引数がどのような意味なのかは、mflagパッケージを読む時にじっくり見たいと思います。デフォルトコメントが書かれているので、そこから判断して頂いてもいいかと思います。

処理の流れとしては、


  1. versionフラグがtrueの時、version情報を出力して終了
  2. Hosts(?)の長さが0(指定されていない時)に環境変数DOCKER_HOSTを取得
    1. DOCKER_HOSTが未定義または、Daemonとして動作する時はデフォルトのUnixSocketを保持する。
      1. ちなみに、デフォルトのUnixSocketのパスは/var/run/docker.sockなので、Macだと存在しないと怒られて動作しないので、-HオプションでSocketを指定する。
  3. -bと--bipオプションが両方指定してあるとエラーになる。
  4. -Dか--debugオプションが指定してある場合は、環境変数DEBUGを1にする。
  5. -dか--daemonオプションが指定されているとDaemonモードで動作する。
    1. ※こちらは今回読んでいないので、中身はまだわかりません。
  6. 指定されていない場合は、clientモード(docker run XXXとかで動かすモード)の処理
    1. TLSを使うかどうかのチェック
    2. client.NewDockerCli()を呼び出し、clientオブジェクトを取得
      1. TLSを使うかどうかの違いは最後の引数がnilか、configが指定してあるかの違い。
    3. ParseCommands()でコマンドの解析とサブコマンドの実行が行われる。
      1. 解析だけかと思ったら実行もされていた。
今回のポイントとして、Unused Importsを使ったパッケージの初期化処理が便利だということと、strings.SplitN()を使って、最大N個までの分割で済ませるというAPIがあることが、新たな発見でした。

特に、Unused Importsはsql/driverあたりでも使われるのですが、その時は、interfaceのみだから、interfaceを認識させるために使うと思っていましたが、init()関数が呼び出されることで、ドライバの初期化ができるというのは、初期化処理の呼び出しをいちいち書かなくても良いという点でいい発見でした。(使う時があるかどうかは別にして…)

次回はdockerのサブコマンドである、apiパッケージを読み進めたいと思います。
新たな発見が出るかな?