dockerコンテナのサイズ問題

docker

dockerコンテナはなるべく小さいサイズで作っておくほうが取り回しが利きやすく便利ですが、公式が配布しているイメージはDebianやUbuntuベースだったりすることが多く、そもそものサイズが大きい傾向があります。

最近は公式のイメージも省サイズ化が進んでいる感がありますが、Ubuntuなどバイナリパッケージを使うディストリビューションがベースだとバイナリが最新に追いついていなかったりで、ちょと新しいことをしようとすると結局gccを始めとしたツールチェーンが必要になるケースが多いと思います。

一度ツールチェーンを入れてしまうと削除も面倒なので、そのまま実行環境のコンテナにも含まれっぱなしになり、無駄に容量の大きいコンテナを走らせている、ということになっていないでしょうか。

Gentooを使うという選択

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に関する日本語の情報は皆無なので、誰かの助けになれば幸いです。

▼お知らせ
FirstLogicでは現在、開発メンバーを募集しています。
詳細は こちら をご覧ください。