【Go言語】goでimageをpullする

## 「docker pull」 をGo言語で

以下のコードを実行すると`docker pull httpd`と同様の動作を行えます

```go
package main

import (
	"context"
	"io"
	"os"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
)

const (
	dockerClientVersion = "1.42"
)

func main() {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion(dockerClientVersion))
	if err != nil {
		panic(err)
	}
	defer cli.Close()

	reader, err := cli.ImagePull(ctx, "docker.io/library/httpd", types.ImagePullOptions{})
	if err != nil {
		panic(err)
	}
	io.Copy(os.Stdout, reader)
}
```

### コードの解説

以下のコードでは、ImagePull関数を使用して、httpdのイメージをDockerの公式リポジトリからプルしています。この関数は2つの戻り値を返します。

1つ目はreaderで、これはプルしたイメージのデータを読み取るためのオブジェクトです。二つ目はerrで、これはイメージのプル操作中にエラーが発生した場合にその情報を保持します。

```go
reader, err := cli.ImagePull(ctx, "docker.io/library/httpd", types.ImagePullOptions{})
if err != nil {
  panic(err)
}
 ```

 readerには逐次文字列が投げ込まれていくので`io.Copy`を使って標準出力を行います。

```go
io.Copy(os.Stdout, reader)
```

実際に実行すると以下のように`docker pull`を行ったときと同じような出力が行われます。

```bash
$ go run main.go
{"status":"Pulling from library/httpd","id":"latest"}
{"status":"Already exists","progressDetail":{},"id":"2c6d21737d83"}
{"status":"Pulling fs layer","progressDetail":{},"id":"d1bd5114fbcb"}
{"status":"Pulling fs layer","progressDetail":{},"id":"4f4fb700ef54"}
{"status":"Pulling fs layer","progressDetail":{},"id":"076d30352063"}
{"status":"Pulling fs layer","progressDetail":{},"id":"1efe13fa30a0"}
{"status":"Pulling fs layer","progressDetail":{},"id":"01bce57a32a8"}
{"status":"Waiting","progressDetail":{},"id":"1efe13fa30a0"}
{"status":"Waiting","progressDetail":{},"id":"01bce57a32a8"}
{"status":"Downloading","progressDetail":{"current":146,"total":146},"progress":"[==================================================\u003e]     146B/146B","id":"d1bd5114fbcb"}
{"status":"Download complete","progressDetail":{},"id":"4f4fb700ef54"}
{"status":"Verifying Checksum","progressDetail":{},"id":"d1bd5114fbcb"}
{"status":"Download complete","progressDetail":{},"id":"d1bd5114fbcb"}
{"status":"Extracting","progressDetail":{"current":146,"total":146},"progress":"[==================================================\u003e]     146B/146B","id":"d1bd5114fbcb"}
{"status":"Extracting","progressDetail":{"current":146,"total":146},"progress":"[==================================================\u003e]     146B/146B","id":"d1bd5114fbcb"}
{"status":"Downloading","progressDetail":{"current":38872,"total":3823952},"progress":"[\u003e                                                  ]  38.87kB/3.824MB","id":"076d30352063"}
{"status":"Downloading","progressDetail":{"current":3201351,"total":3823952},"progress":"[=========================================\u003e         ]  3.201MB/3.824MB","id":"076d30352063"}
{"status":"Verifying Checksum","progressDetail":{},"id":"076d30352063"}
{"status":"Download complete","progressDetail":{},"id":"076d30352063"}
{"status":"Pull complete","progressDetail":{},"id":"d1bd5114fbcb"}
{"status":"Extracting","progressDetail":{"current":32,"total":32},"progress":"[==================================================\u003e]      32B/32B","id":"4f4fb700ef54"}
{"status":"Extracting","progressDetail":{"current":32,"total":32},"progress":"[==================================================\u003e]      32B/32B","id":"4f4fb700ef54"}
{"status":"Pull complete","progressDetail":{},"id":"4f4fb700ef54"}
{"status":"Extracting","progressDetail":{"current":65536,"total":3823952},"progress":"[\u003e                                                  ]  65.54kB/3.824MB","id":"076d30352063"}
{"status":"Extracting","progressDetail":{"current":3080192,"total":3823952},"progress":"[========================================\u003e          ]   3.08MB/3.824MB","id":"076d30352063"}
{"status":"Extracting","progressDetail":{"current":3823952,"total":3823952},"progress":"[==================================================\u003e]  3.824MB/3.824MB","id":"076d30352063"}
{"status":"Pull complete","progressDetail":{},"id":"076d30352063"}
{"status":"Downloading","progressDetail":{"current":293,"total":293},"progress":"[==================================================\u003e]     293B/293B","id":"01bce57a32a8"}
{"status":"Download complete","progressDetail":{},"id":"01bce57a32a8"}
{"status":"Downloading","progressDetail":{"current":334150,"total":32418239},"progress":"[\u003e                                                  ]  334.1kB/32.42MB","id":"1efe13fa30a0"}
{"status":"Downloading","progressDetail":{"current":4315462,"total":32418239},"progress":"[======\u003e                                            ]  4.315MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Downloading","progressDetail":{"current":8943942,"total":32418239},"progress":"[=============\u003e                                     ]  8.944MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Downloading","progressDetail":{"current":15522118,"total":32418239},"progress":"[=======================\u003e                           ]  15.52MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Downloading","progressDetail":{"current":20470086,"total":32418239},"progress":"[===============================\u003e                   ]  20.47MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Downloading","progressDetail":{"current":25413958,"total":32418239},"progress":"[=======================================\u003e           ]  25.41MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Downloading","progressDetail":{"current":30341446,"total":32418239},"progress":"[==============================================\u003e    ]  30.34MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Verifying Checksum","progressDetail":{},"id":"1efe13fa30a0"}
{"status":"Download complete","progressDetail":{},"id":"1efe13fa30a0"}
{"status":"Extracting","progressDetail":{"current":327680,"total":32418239},"progress":"[\u003e                                                  ]  327.7kB/32.42MB","id":"1efe13fa30a0"}
{"status":"Extracting","progressDetail":{"current":2621440,"total":32418239},"progress":"[====\u003e                                              ]  2.621MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Extracting","progressDetail":{"current":8847360,"total":32418239},"progress":"[=============\u003e                                     ]  8.847MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Extracting","progressDetail":{"current":19005440,"total":32418239},"progress":"[=============================\u003e                     ]  19.01MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Extracting","progressDetail":{"current":23592960,"total":32418239},"progress":"[====================================\u003e              ]  23.59MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Extracting","progressDetail":{"current":24903680,"total":32418239},"progress":"[======================================\u003e            ]   24.9MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Extracting","progressDetail":{"current":28835840,"total":32418239},"progress":"[============================================\u003e      ]  28.84MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Extracting","progressDetail":{"current":32418239,"total":32418239},"progress":"[==================================================\u003e]  32.42MB/32.42MB","id":"1efe13fa30a0"}
{"status":"Pull complete","progressDetail":{},"id":"1efe13fa30a0"}
{"status":"Extracting","progressDetail":{"current":293,"total":293},"progress":"[==================================================\u003e]     293B/293B","id":"01bce57a32a8"}
{"status":"Extracting","progressDetail":{"current":293,"total":293},"progress":"[==================================================\u003e]     293B/293B","id":"01bce57a32a8"}
{"status":"Pull complete","progressDetail":{},"id":"01bce57a32a8"}
{"status":"Digest: sha256:bb56126969beb90ea4912aa6353be3b419b05ca89e1c12621d4457cd5c02ed16"}
{"status":"Status: Downloaded newer image for httpd:latest"}
```

終了後、イメージの一覧を確認すると最新版のhttpdイメージが無事取り込まれていました。