DockerfileのCOPY --fromでお手軽にBusyBoxを足す
Dockerやk8s等でコンテナをデバックする際、どうしてもコンテナの中に入って各種コマンドを打ってみたくなることがあると思います。
しかし、よくできた軽量なコンテナほど余計なものが入っていないので、必要最低限のコマンドすらない……となるのもありがちです。下手するとシェルすら入っていません。
そんな時に備えてDockerfileに
# タグ等は適宜変更してください
COPY /bin/busybox /bin/busybox
を書き足しておくといいかもよ、という話をまとめた記事です。
BusyBoxとは
BusyBoxは、数多くのUNIXコマンド類を一つのバイナリに詰め合わせたものです。例えばsh, vi, grep, awkなど馴染みのあるコマンドがサブコマンドの形で格納されています。
$ busybox echo 'Hello BusyBox'
Hello BusyBox
BusyBoxはたくさんコマンドが入っているのに1MB程度のサイズしかありません。そのため、これをコンテナイメージに含めておくと、大きなコストを伴わずにコンテナ内でできることを増やせます。
コンテナイメージにBusyBoxを入れる
そういうわけで、コンテナイメージにBusyBoxを入れることを考えます。シングルバイナリなので足す方法はいろいろあると思いますが、簡潔なのは最初に紹介した書き方です。
FROM hello-world
COPY /bin/busybox /bin/busybox
すなわち、Dockerfile中のCOPY --from
でBusyBoxのDockerイメージを指定し、その中にあるbusybox
バイナリをコピーします。
--from
はマルチステージビルドの前段ステージを指すフラグじゃなかったの? と思うかもしれません。Dockerfileのドキュメントを読むと、こんなことが書かれています。
Optionally COPY accepts a flag --from=<name> that can be used to set the source location to a previous build stage (created with FROM .. AS <name>) that will be used instead of a build context sent by the user. In case a build stage with a specified name can’t be found an image with the same name is attempted to be used instead.
https://docs.docker.com/engine/reference/builder/#copy
どうやら指定された名前がステージ名に見つからなかったとき、Dockerはそれをイメージ名として解決しようとするようです。結果的にこのコマンドはbusybox
イメージを解決してその中のバイナリをコピーしてくれます。
まとめ
- BusyBoxというのがある。軽量でいろいろなコマンドが詰まっているので何かの時に便利
- DockerfileのCOPY --fromは参照先に別のイメージを選ぶこともできる
参考書籍
筆者はこのテクニックを『Kubernetesで実践するクラウドネイティブDevOps』で知りました。
Discussion