dockerコンテナのサイズ問題
dockerコンテナはなるべく小さいサイズで作っておくほうが取り回しが利きやすく便利ですが、公式が配布しているイメージはDebianやUbuntuベースだったりすることが多く、そもそものサイズが大きい傾向があります。
最近は公式のイメージも省サイズ化が進んでいる感がありますが、Ubuntuなどバイナリパッケージを使うディストリビューションがベースだとバイナリが最新に追いついていなかったりで、ちょと新しいことをしようとすると結局gccを始めとしたツールチェーンが必要になるケースが多いと思います。
一度ツールチェーンを入れてしまうと削除も面倒なので、そのまま実行環境のコンテナにも含まれっぱなしになり、無駄に容量の大きいコンテナを走らせている、ということになっていないでしょうか。
Gentooを使うという選択
Gentoo Linuxは各パッケージをソースから管理する都合上ビルドの時間がかかりますが、portageの仕組みが素晴らしく依存関係の解決がしっかりしているので一部パッケージの最新動向を追いつつシステム全体はまったり維持、という使い方の場合は逆に管理が楽だったりします。
ということで、dockerコンテナもgentooベースで構築したくなるのですが、通常のgentooをそのまま使おうとすると当然ビルド環境が含まれてしまい旨味がないので、一工夫必要になります。
gentoo-bbでコンテナを自動作成
githubで公開されているgentoo-bbはgentooベースのdockerイメージ自体を依存関係で管理し、コマンドから生成、更新できるツールです。gentooの柔軟性を生かしつつ、ビルド用のイメージと完成イメージを分けることでイメージの省サイズ化が実現できます。
また、各イメージがそれぞれ依存関係を保持し、ビルド済みパッケージをバイナリでキャッシュしておくことで、更新の際も最小限のリビルドで済むように工夫されています。
容量の削減効果は、例えばNginxの場合普通にgentooで作ると300MB、Ubuntu系のもので1GB以上なのが、gentoo-bbでは17MB程度になるとのこと。
実際に私が試してみたところ、mariadbのクライアントとnodejsを加えたrailsのイメージで60MB程度になりました。公式だと300MB以上なので、かなり効果があるといえそうです。
作成してみる
それでは実際に試してみましょう。まずはデフォルトで提供されているbusyboxを作ってみます。
$ git clone https://github.com/edannenberg/gentoo-bb.git $ cd gentoo-bb $ ./build.sh -s build gentoobb/busybox
それなりに時間がかかるのでお茶でもどうぞ。終わったら、イメージを確認してみましょう。
$ docker images |grep busybox gentoobb/busybox 20161103 260feecbe9fb 7 minutes ago 1.271 MB gentoobb/busybox latest 260feecbe9fb 7 minutes ago 1.271 MB gentoobb/bob-musl-busybox 20161103 110906f893ee 7 minutes ago 1.705 GB gentoobb/bob-musl-busybox latest 110906f893ee 7 minutes ago 1.705 GB busybox latest e02e811dd08f 4 weeks ago 1.093 MB
bob-musl-busyboxというのはビルド用のコンテナです。gentooのビルド環境が含まれるのでこのサイズになりますが、完成したbusyboxイメージは目的のバイナリのみのため、本物と大差ないサイズになりました。
railsイメージを作成する
自分のnamespaceでイメージを作成してみましょう。まずはディレクトリと設定ファイルを作ります。
$ mkdir -p dock/yours/images $ cat <<END > dock/yours/build.conf AUTHOR="Your Name<you@example.com>" DEF_BUILD_CONTAINER="gentoobb/bob" CONTAINER_ENGINE="docker" END
次に、railsイメージの設定を作成します。
$ mkdir -p dock/yours/images/rails $ vi dock/yours/images/rails/Buildconfig.sh $ vi dock/yours/images/rails/Dockerfile.template
それぞれ、内容は以下のようにします。
何となく分かるかと思いますが4行目で対象のパッケージを指定したあと、ビルド中の各タイミングで呼ばれるフックでUSEフラグの操作などを記述しています。意味はgentoobbの設定などを参考にして理解してください。
Buildconfig.sh
# # build config # PACKAGES="app-arch/pbzip2 net-misc/curl dev-db/mariadb net-libs/http-parser dev-libs/libuv dev-libs/openssl" configure_bob() { # nodejs ebuild pulls in python for node-gyp # we only want the runtime deps for node in this image NODEJS_VERSION=$(get_package_version 'net-libs/nodejs') # nodejs currently requires openssl with ECDH :/ #emerge -C net-misc/openssh unprovide_package dev-libs/openssl update_use 'dev-libs/openssl' '-bindist' emerge dev-libs/openssl net-libs/nodejs } configure_rootfs_build() { # Reinstall zlib unprovide_package sys-libs/zlib # Mariadb client only update_use 'dev-db/mariadb' '-server' # Reinstall curl, need at build time unprovide_package net-misc/curl } finish_rootfs_build() { copy_gcc_libs tar xjvf "/packages/x86_64-pc-linux-gnu/net-libs/nodejs-${NODEJS_VERSION}.tbz2" -C "${EMERGE_ROOT}" log_as_installed "manual_install" "net-libs/nodejs-${NODEJS_VERSION}" }
こちらは普通にDockerfileのテンプレートになります。
Dockerfile.template
FROM gentoobb/ruby MAINTAINER ${MAINTAINER} ADD rootfs.tar / ADD gemrc /etc RUN gem install bundler
ファイルができたら、ビルドしてみましょう。
$ ./build.sh build yours/rails
サイズはどうでしょうか。
$ docker images |grep rails yours/rails 20161103 74579c84407d About an hour ago 201.9 MB yours/rails latest 74579c84407d About an hour ago 201.9 MB rails latest b84ede6bed10 21 hours ago 837.8 MB
200MBぐらいなので、公式よりも小さくできました。
まとめ
以上、gentoo-bbを使って必要な要求を満たすイメージをビルドする方法を紹介しました。
gentoo-bbを使うと、gentooの柔軟性を活かして必要なバイナリパッケージだけのイメージを簡単に作成できます。ビルドに時間がかかるのが玉にキズですが、うまく使えば効率的なdockerシステムが作れるのではないかと思います。
現在のところ、私の知る限りgentoo-bbに関する日本語の情報は皆無なので、誰かの助けになれば幸いです。
詳細は こちら をご覧ください。