前回エントリ↓でコードからのイメージのpullが動かなくてあっれおかしーなーとなって悔しかったのでリベンジです。
tl;dr
client.ImagePull
の返り値はio.ReadCloser
型とerror
型- この
io.ReadCloser
が、イメージのpullのprogressなどを表すHTTPのストリーム - このストリームへの書き込みが終わる(つまり
docker pull
が完了する)まで待つ必要があった
以下読まなくてよいです
動かないコード
func main() { c, err := client.NewEnvClient() if err != nil { panic(fmt.Errorf("NewEnvClient: %v", err)) } ctx := context.Background() // "debian"(:latestは省略可)のpullを試みる rp, err := c.ImagePull(ctx, "debian", types.ImagePullOptions{}) if err != nil { panic(fmt.Errorf("ImageSave: %v", err)) } defer rp.Close() // エラーさえ無ければイメージのpullが成功していると誤解していた cc := &container.Config{Image: "debian"} hc := &container.HostConfig{AutoRemove: true} nc := &network.NetworkingConfig{} body, err := c.ContainerCreate(ctx, cc, hc, nc, "bar") if err != nil { panic(fmt.Errorf("ContainerCreate: %v", err)) // 結局ここで"debianなんてイメージは無い!"と叱られる } fmt.Printf("Created Container:\n%+v\n", body) }
動くコード
前後省略します
func main() { /* 省略(クライアントの初期化とかする) */ // "debian"(:latestは省略可)のpullを試みる rp, err := c.ImagePull(ctx, "debian", types.ImagePullOptions{}) if err != nil { panic(fmt.Errorf("ImageSave: %v", err)) } defer rp.Close() // {{{ こっからが味噌!! // こういう構造のバッファが書き込まれる payload := struct { ID string `json:"id"` Status string `json:"status"` Progress string `json:"progress"` ProgressDetail struct { Current uint16 `json:"current"` Total uint16 `json:"total"` } `json:"progressDetail"` }{} // bufio.Scannerマジでかわいい scanner := bufio.NewScanner(rp) for scanner.Scan() { json.Unmarshal(scanner.Bytes(), &payload) fmt.Printf("\t%+v\n", payload) } // }}} ここまでが味噌!! /* 省略(得られたイメージを指定してコンテナつくったりする) */ }
上記では、bufio.Scanner
を使ってHTTPのEOFまで待っている。ついでに、毎バッファ書き込みされるレスポンスを取り出して上げている。
↓こういうきれいな感じのペイロードが送られてくる。
Scanner使わないんだったらioutil.ReadAll
かなー他にストリームが終わるの同期的に待つのどうすっかなーと思ってググりました。
- Golangでのstreamの扱い方を学ぶ - Carpe Diem
- Streaming data in Go, without bytes.Buffer – Stupid Gopher Tricks – Medium
- go - How to find EOF while reading from a file - Stack Overflow
今回のように毎ペイロードが独立して意味のあるものであれば、Scanner使うのが良い気がするものの、もっと良い(単にReaderのEOFを待つための)方法があれば教えてくださいm(_ _)m
雑感
- Goのコードから
github.com/docker/docker/client
を使って (1) イメージのpull (2) コンテナ起動 が実現されたので、これでほぼ心置きなく俺々Dockerクライアントを自作できますね!やったね! - 腰椎椎間板ヘルニアになっちゃった。腰痛ぇ。
『腰痛持ちエンジニアが選ぶマットレス5選』みたいなのください
— エッチなリツイートをします (@otiai10) 2017年5月25日
DRYな備忘録として

- 作者: Adrian Mouat,Sky株式会社玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/08/17
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る

Docker : A Quick-Start Beginner's Guide (English Edition)
- 作者: Andy Hayes
- 発売日: 2017/01/23
- メディア: Kindle版
- この商品を含むブログを見る

Infrastructure as Code ―クラウドにおけるサーバ管理の原則とプラクティス
- 作者: Kief Morris,宮下剛輔,長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2017/03/18
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る