今回も前回に引き続き、Dockerのソースコードを読み進めました。
前回は、クライアントでのコマンド実行のところまで読んだので、今回は、docker runコマンドの実行部分を読んでみました。
該当の場所は、api/client/command.goの1776行目にある、
func (cli *DockerCli) CmdRun(args ...string) error {
からとなります。
処理の概要は
- コマンドの解析(ParseSubCommand)
- ContainerIDFileが存在しなければ、ContainerIDFileを生成する。
- ただし、ホストの設定(hostConfig)で指定されている場合のみ。
- ContainerIDFileは最後に削除する。
- cli.call("POST", "/containers/create?")で、デーモン側にコンテナの作成を指示。
- ファイルがない(httpのレスポンスが404の時)時は、コンテナImageがないので、imageを作成を指示する。(これも、cli.call())
- コンテナの作成の結果を受け取る。
- コンテナにattach(cli.hijack("/containers/"+runResult.Get("Id")+"/attach?"))
- コンテナの開始(cli.call("/containers/"+runResult.Get("Id")+"/start"))
- 結果を取得
結局クライアントからはデーモンに向かってプロセス通信しているだけで、何も処理がありませんでしたので、デーモン側の処理を読むことで、コンテナの配置とか、処理の実行の部分の理解を深めることができそうです。
デーモンはいつ起動させるのか?
Ubuntuだと、サービスとしてPC起動時に起動してしまうようです。また、Macだと、boot2dockerを使ってサービスを起動させた状態で使っています。
Windowsだとどうやら無理みたいですw(中身をみると、syscallをバリバリ使っているので、Windowsとは相性が悪そうです…。)
さて、細かい処理を(複雑で時間がかかるので)見ていないのですが、処理の概要は読めました。
今回のポイントですが、プロセス通信をする時に中身では、httpを使っています。
標準パッケージのnet/http/httputilを使って、http通信をしていました。
httputil.ClientConnを使ったリクエストを行う場合、net.Connを自分で指定させるため、Socketを自分で作ります。今回は、Unixドメインソケットだったり、tcpソケットだったりするわけです。(Macだと-Hオプションで指定したURL(私の環境だとtcp://localhost:[Port])を使ってソケットを生成されるようです)
よく考えると、これまでnet/http周りはじっくり読むということをしていなかったので、またのタイミングで読みたいと思います。
ということで、次回はデーモン側のソースコードを読む予定です。