プログラムからDockerのイメージやコンテナの操作をして、必要に応じてコンテナを起動したり停止したりというサービスをつくろうとしていた。
いろいろ調べたので、Go言語(以下、Golangと呼ぶ)からDockerのイメージやコンテナの操作をする方法をまとめる。
Dockerはコンテナ仮想化ツールで、Golangで開発されている。
そのため、Docker Engineのクライアント(moby/client)をそのままGolangで使える。
※ Dockerの詳しい説明は省略する
今回はMobyを使ってイメージの作成・削除、コンテナの起動・停止を行う。
環境は以下のとおり。
- Mac OSX
- go 1.8.3
- Docker for Mac 17.6.1-ce
Dockerをインストールする
Macで開発していたので、Docker for Macを使った。
リンク先からダウンロードして、インストールする。
WindowsならDocker for Windowsを使うと楽だ。
Linux(CentOSなど)で使うなら、以下の記事にDockerインストール用のシェルスクリプトが書いてあるので、参考にしてほしい。
Mobyのインストール
go getでインストールする場合は、以下のコマンドを実行する
$ go get -u github.com/moby/moby
depを使っている場合は、
github.com/moby/moby/client
をimportしてからdep ensure
を実行する。するとvendorディレクトリにインストールされる。私の場合はdepを使っているので後者のコマンドを実行する。
Dockerイメージの取得からコンテナ起動まで
開発準備は整ったので、実際にDockerイメージの取得からコンテナ起動までを行う。
クライアントの生成
import (
"io"
"os"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/moby/moby/client"
"golang.org/x/net/context"
)
func main() {
ctx := context.Background()
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
// 略
}
ここのimportで注意すべき点がある。執筆時点ではクライアントはmobyなのだが、typesについてはすべてdockerを参照している。
moby配下にもtypesがあり、最初はそちらを参照していたところ以下のようなエラーがでてちょっとハマった。
cannot use "/github.com/moby/moby/api/types".ContainerListOptions literal (type "/github.com/moby/moby/api/types".ContainerListOptions) as type "/github.com/docker/docker/api/types".ContainerListOptions in argument to cli.ContainerList'
イメージの取得
$ docker pull [image]
_, err = cli.ImagePull(ctx, "docker.io/library/alpine", types.ImagePullOptions{})
if err != nil {
panic(err)
}
aplineのイメージをimagePullで取得する。
コンテナの作成
$ docker build [path | url]
resp, err := cli.ContainerCreate(ctx, &container.Config{
Image: "alpine",
Cmd: []string{"echo", "hello world"},
}, nil, nil, "name")
if err != nil {
panic(err)
}
先ほどaplineのイメージを取得したので、ContainerCreateでコンテナの作成を行う。
コンテナ、ホスト、ネットワークの設定ができる。
今回はコンテナの設定(container.Config)だけを行う。
aplineのイメージを使い、起動時には
echo "hello world"
を実行する。コンテナの実行
$ docker start [container]
if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
panic(err)
}
ContainerCreateではContainerCreateCreatedBodyという戻り値があり、コンテナのIDや警告を取得することができる。
ContainerStartでコンテナを実行する。その際に戻り値のコンテナIDを使っている。
コンテナの実行が終わるまで待機
$ docker wait [container]
if _, err = cli.ContainerWait(ctx, resp.ID); err != nil {
panic(err)
}
ターミナルからDockerコンテナを実行するときはあまり使わないが、ContainerWaitで指定されたコンテナの状態がnot-running, next-exit, removedのいずれかになるまで待機する。
コンテナのログを取得
$ docker logs [image]
out, err := cli.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true})
if err != nil {
panic(err)
}
io.Copy(os.Stdout, out)
ContainerWait同様にあまり使わない気がするが、ContainerLogsでコンテナで生成されたログをio.ReadCloserに返してくれるので、io.Copy関数を使い標準出力に表示する。
コードの全体
package main
import (
"io"
"os"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/moby/moby/client"
"golang.org/x/net/context"
)
func main() {
ctx := context.Background()
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
_, err = cli.ImagePull(ctx, "docker.io/library/alpine", types.ImagePullOptions{})
if err != nil {
panic(err)
}
resp, err := cli.ContainerCreate(ctx, &container.Config{
Image: "alpine",
Cmd: []string{"echo", "hello world"},
}, nil, nil, "")
if err != nil {
panic(err)
}
if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
panic(err)
}
if _, err = cli.ContainerWait(ctx, resp.ID); err != nil {
panic(err)
}
out, err := cli.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true})
if err != nil {
panic(err)
}
io.Copy(os.Stdout, out)
}
を実行すると、コンソールにhello worldと表示される。
$ go run main.go
hello world
その他のよく使いそうな関数
Dockerを使っていると、これまでに紹介したもの以外によく使うコマンドがある。
イメージ一覧の取得
$ docker images
list, err := cli.ImageList(ctx, types.ImageListOptions{})
if err != nil {
panic(err)
}
for _, image := range list {
fmt.Printf("ID: %s, Labels: %s, Container: %d, Size: %d\n", image.ID, image.Labels, image.Containers, image.Size)
}
ImageListでイメージ一覧を取得でき、ImageSummaryを配列を返す。
私の環境で実際に実行すると以下のようなリストが表示される。
ID: sha256:328..., Labels: map[build-date:20170801 license:GPLv2 name:CentOS Base Image vendor:CentOS], Container: -1, Size: 192510595
ID: sha256:21e..., Labels: map[], Container: -1, Size: 66833621
ID: sha256:732..., Labels: map[], Container: -1, Size: 3965955
ID: sha256:893..., Labels: map[], Container: -1, Size: 714537141
ID: sha256:a85..., Labels: map[], Container: -1, Size: 183754122
ID: sha256:b6c..., Labels: map[], Container: -1, Size: 689015971
ID: sha256:47b..., Labels: map[], Container: -1, Size: 351873541
ID: sha256:c9e..., Labels: map[], Container: -1, Size: 389739875
コンテナ一覧の取得
$ docker ps -a
containers, err := cli.ContainerList(ctx, types.ContainerListOptions{
All: true,
})
if err != nil {
panic(err)
}
for _, container := range containers {
fmt.Printf("ID: %s, Name: %s, Image: %s, Command: %s\n", container.ID, container.Names, container.Image, container.Command)
}
ContainerListでコンテナ一覧が取得できる。ContainerListOptionsで
All: true
にすることで、停止中のコンテナも表示できる。また、ContainerListはContainerの配列を返す。
私の環境で実際に実行すると以下のようなリストが表示される。
ID: 5108..., Name: [/goofy_noether], Image: alpine, Command: echo 'hello world'
ID: 2709..., Name: [/peaceful_goldstine], Image: alpine, Command: echo 'hello world'
ID: 2809..., Name: [/redis], Image: redis, Command: docker-entrypoint.sh redis-server
コンテナの削除
$ docker rm [container]
err = cli.ContainerRemove(ctx, "id", types.ContainerRemoveOptions{})
if err != nil {
panic(err)
}
ContainerRemoveで指定したIDのコンテナを削除できる。
だいたいこんな感じだろうか。
その他の関数については、mobyクライアントのドキュメントを読めばわかると思う。
ただドキュメントもそこまで親切ではなく、オプションを指定したらどうなるかなど書かれていない。そんなときはDocker EngineのAPIリファレンスを見ることをオススメする。
Dockerfileを用いたイメージ作成は、結構ハマったので別記事として後日書く。
追記: 2017/09/04 08:00
参考サイト
- moby/moby/client - GoDoc
- Docker Engine API and SDKs | Docker Documentation
- Docker Engine API v1.30 Reference
以上
written by @bc_rikko
0 件のコメント :
コメントを投稿