Goならわかるシステムプログラミング ― 第20回 Go言語とコンテナ
http://ascii.jp/elem/000/001/502/1502967/
Goならわかるシステムプログラミングの中で、GoとlibcontainerライブラリでLinuxコンテナを実装する回があるのだが、
実装したコンテナはLinux上でしかgo build
できないし、起動もできなかった。VirtualBoxなどでも良いが、Dockerで環境を用意するようにした。
今回作成したDockerfileなどは以下にある。
budougumi0617/gsp/ch17/container
https://github.com/budougumi0617/gsp/tree/master/ch17/container
TL;DR
- 「Goならわかるシステムプログラミング Go言語とコンテナ」のサンプルコードをmacOSやWindowsでも動かせるようにDockerfileを作成した
- 起動したAlpineコンテナの中でlibcontainerで実装した自作(写経)コンテナを起動できた
docker run
するときに--privileged
オプションをつけておくこと
背景
Goならわかるシステムプログラミングの「第17章 Go言語とコンテナ」では libcontainerライブラリを使ってGoでコンテナを実装し起動する。
Goならわかるシステムプログラミング
https://amazon.jp/dp/4908686033
opencontainers/runc/libcontainer
https://github.com/opencontainers/runc/tree/master/libcontainer
Web上の連載で言うと第20回になる。
Goならわかるシステムプログラミング ― 第20回 Go言語とコンテナ
http://ascii.jp/elem/000/001/502/1502967/
ただし、Linux上でしか起動しないコンテナなのでmacOS(Windows)上ではgo build
すらできない。
本中のサンプルコードを実装する
Dockerfileをそのまま利用する場合は本(連載)の中のコードを_main.go
という名前で写経する。
https://github.com/budougumi0617/gsp/blob/master/ch17/container/_main.go
Linux上でそれなりに準備しておかないとビルドに失敗するので、_
付きの名前で後で作成するコンテナ内でしかビルドしないようにしておいたほうが良い。
build constraints
で// +build linux
もつけているのだが、自分のCircle CI
のビルドだとLinux上でのビルドのはずなのに失敗した。
Dockerfileを作成する
Dockerfileの内容は以下。alpineベースのコンテナにgo build
するときに要求されるライブラリを入れた後、ビルドするだけの単純な構成。
FROM golang:1.9.4-alpine3.7
RUN apk add --update openssl-dev pcre-dev git gcc musl-dev linux-headers sudo
WORKDIR /go/src/github.com/budougumi0617/gsp/ch17/container/
ADD _main.go ./main.go
ADD rootfs ./rootfs/
RUN go get -v .
RUN go build main.go
CMD echo "test"
alpine
コンテナだとインクルードファイルなどが入っていないのでもろもろapk add
しておく。
また、コンテナに入って自作コンテナでいろいろコマンドを実行するのが目的のためエントリはただのecho
にしてある。
本(連載)に記載されているrootfs
ディレクトリにalpineコンテナから抽出したもろもろのファイルを入れる作業は
Dockerfile外で行う必要があるので注意。
$ docker pull alpine
$ docker run --name alpine alpine
$ docker export alpine > alpine.tar
$ docker rm alpine
$ mkdir rootfs
$ tar -C rootfs -xvf alpine.tar
これで自作(写経)コンテナを実行してみる準備ができた。
docker runするときは–privilegedオプションをつけること
docker build
の中でgo build
するので、あとはコンテナに入って実際に起動してみる。
ここでオプションをつけずにそのままdocker run
をすると以下のようなエラーで終了してしまう。
$ docker build -t build-container .
$ docker run -it build-container /bin/ash
/go/src/github.com/budougumi0617/gsp/ch17/container # sudo ./main
WARN[0000] signal: killed
2018/02/14 00:43:37 container_linux.go:348: starting container process caused "process_linux.go:279: applying cgroup configuration for process caused \"mkdir /sys/fs/cgroup/cpuset/system: read-only file system\""
syscall
する権限が不足しているのが原因らしいので、--privileged
をつけてdocker run
する。
$ docker build -t build-container . --no-cache=true
$ docker run --privileged -it build-container /bin/ash
/go/src/github.com/budougumi0617/gsp/ch17/container # ./main
/bin/sh: can't access tty; job control turned off
/ # /bin/hostname
testing
/ # exit
/go/src/github.com/budougumi0617/gsp/ch17/container # exit
ちょっとTTYの設定は出来ていないが、ちゃんと実行することができた。
おわりに
alpine linuxベースのコンテナを実行させるためにalpine linuxコンテナを作るというやや本末転倒気味のことしているのはご愛嬌。
頑張れば作業工程のalpine.tar
を作る工程は削除できそうなのだが、目的は達成したのでここまでにしておく。
去年の今頃Dockerの本一冊読んだのだが、Dockerfileの書き方をすっかり忘れていた。やはり日頃の継続と反復が大事である。
参考
Goならわかるシステムプログラミング
https://amazon.jp/dp/4908686033
Goならわかるシステムプログラミング ― 第20回 Go言語とコンテナ
http://ascii.jp/elem/000/001/502/1502967/
budougumi0617/gsp/ch17/container
https://github.com/budougumi0617/gsp/tree/master/ch17/container
opencontainers/runc/libcontainer
https://github.com/opencontainers/runc/tree/master/libcontainer
GoのBuild Constraintsに関するメモ
https://qiita.com/hnw/items/7dd4d10e837158d6156a
Docker privileged オプションについて
https://qiita.com/muddydixon/items/d2982ab0846002bf3ea8