GoのコードからDockerコンテナの起動を実装する
やったこと
- docker clientをGoのコードからimportする
- container作成
- container起動
- container停止(& 自動削除)
苦労したこと
- けっこうdocker(現moby)のコードの移り変わりが激しくて、vendorを固定するのが苦労した
- これとか
できなかったこと
- コードからのimage pull
- コードからのimage save
- それを元に上記を実行
- 【追記】できた
main.go
package main import ( "context" "fmt" "time" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" "github.com/docker/docker/client" "github.com/docker/go-connections/nat" ) func main() { c, err := client.NewEnvClient() if err != nil { panic(fmt.Errorf("NewEnvClient: %v", err)) } ctx := context.Background() /* 後述する「うごかなかったもの」がここに来ます */ // 1) コンテナをつくる cc := &container.Config{ Image: "nginx", ExposedPorts: nat.PortSet{nat.Port("80"): struct{}{}}, // Entrypoint: strslice.StrSlice{"nginx", "-g", "daemon off;"}, } hc := &container.HostConfig{ // `--port 8080:80` PortBindings: nat.PortMap{ nat.Port("80"): []nat.PortBinding{nat.PortBinding{HostPort: "8080"}}, }, // `--rm` AutoRemove: true, } // docker network らへん nc := &network.NetworkingConfig{} body, err := c.ContainerCreate(ctx, cc, hc, nc, "foo") if err != nil { panic(fmt.Errorf("ContainerCreate: %v", err)) } fmt.Printf("Created Container:\n%+v\n", body) // 2) コンテナのスタート if err := c.ContainerStart(ctx, body.ID, types.ContainerStartOptions{}); err != nil { panic(fmt.Errorf("ContainerStart: %v", err)) } // あること確認 check(ctx, c) // 3) 20秒だけ延命 time.Sleep(20 * time.Second) // 4) コンテナの停止 // --rm を投げてるのでコンテナ自体も削除される timeout := 5 * time.Second if err := c.ContainerStop(ctx, body.ID, &timeout); err != nil { panic(fmt.Errorf("ContainerStop: %v", err)) } // ないこと確認 check(ctx, c) } // コンテナのリストを取得する確認用の関数 func check(ctx context.Context, c *client.Client) { containers, err := c.ContainerList(ctx, types.ContainerListOptions{All: true}) if err != nil { panic(err) } fmt.Println("List of containers") for _, container := range containers { fmt.Printf(" - %s (%s)\n", container.ID, container.Image) } }
これで、 go run main.go
とすると、20秒だけホストの8080にnginxが現れるということになります。
よっしゃ。
うごかなかったもの
rp, err := c.ImagePull(ctx, "nginx:latest", types.ImagePullOptions{}) if err != nil { panic(fmt.Errorf("ImagePull: %v", err)) } defer rp.Close() // エラーは無いんだけど、ContainerCreateで参照できないんだよなあ // じゃあImageSaveかなと思ったけど引数がImageIDsなので、とりあえずハードコードで投げる rs, err := c.ImageSave(ctx, []string{"bf2b4c2d7bf53b4d0d28fa6af60e51c418317d2ada40ed6e5d5c290248d2a469"}) if err != nil { panic(fmt.Errorf("ImageSave: %v", err)) } defer rs.Close() // まあ無いと言われる // 確認用 images, err := c.ImageList(ctx, types.ImageListOptions{}) if err != nil { panic(fmt.Errorf("ImageList: %v", err)) } for _, img := range images { fmt.Printf("%+v\n", img) } // ImagePullで得たio.ReadCloserに色々入ってんのかな? // やたらでかそうだし、もしかしてイメージそのもの?
この部分が動かなかったので、あらかじめホストマシンで docker pull nginx
を実行しないと動かないコードになってしまった。くやしい。次はこれを解決したいです。
DRYな備忘録として
追記
できました otiai10.hatenablog.com
プログラマのためのDocker教科書 インフラの基礎知識&コードによる環境構築の自動化
- 作者: 阿佐志保,山田祥寛
- 出版社/メーカー: 翔泳社
- 発売日: 2015/11/20
- メディア: 大型本
- この商品を含むブログ (3件) を見る
- 作者: Adrian Mouat,Sky株式会社玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/08/17
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
Docker実践入門――Linuxコンテナ技術の基礎から応用まで (Software Design plus)
- 作者: 中井悦司
- 出版社/メーカー: 技術評論社
- 発売日: 2015/09/26
- メディア: 大型本
- この商品を含むブログ (2件) を見る