以下では、これに加えて私がイメージを作る際に周囲からもらったアドバイスや試してみたことなども含めて書いてみます。

可能な限り、必要最小限のサイズのイメージからスタートする

上記ページにも記載があるように、例えばUbuntuよりもDebianを使います。私の場合は趣味的にはUbuntuが好きなのですが、配布用のDockerイメージはDebianのwheezyベースなどで作っています。上記ページにもあるように、これだけで100MBぐらい違ったりします。

RUNでのコマンドをチェーンさせてステージ数を減らす

torusさんの回答にあるものです。DockerではRUNの単位でファイルシステムの更新をおこなうので、仮にあるステージで大きなファイルを追加、その後のステージで当該ファイルを削除しても容量は食いっぱなしとなります。私が過去に作ったものでは、あるソフトウェアのソースを拾ってきてmake && make install、その後にソース一式を削除するところまでをひとつにチェーンさせることで容量削減できました。

不要な中間ファイルは削除する

私がイメージを作成していた時に指摘をもらったものなのですが、/usr/local/src以下にあるソースを拾ってきて、それをmake && make installしたままソースコードを残していたことがありました。

これは、ソースを残しておいたほうが何かといじりやすいと考えての対応でした。さらに言うと、あるソースのスナップショットではなく丸ごとgit cloneしていました。これは様々な実験をおこなう際には便利ですし開発環境のDockerイメージを提供しようという際には良いのです。しかしバイナリ配布でサクッと導入してもらえるようなイメージの構築においてはただの無駄ということで納得しました。

ソースはmake installが終わったら消しましょう。ソースが本当に必要な人は、Dockerfileをforkして自前でなんとかしてくれます多分。

GitHubからソースを拾ってくるものについて、なるべくgit cloneしない

もっと言うと、不要ならgitコマンドをインストールしない(いくらgitのない世界が不安で仕方なくても)。

これも私がとあるイメージを作成していた時にもらった指摘に関するものです。GitHubで配布されているコードを使ったビルドをおこなうならひとまずgit cloneしてくるのが普通だろうという開発脳なのですが、Dockerのイメージを作る際には「えっ、ほんとにgitいる?」と疑うのが肝心です。Debianでgit-coreパッケージをインストールするだけでも数十MBの追加容量が必要となるので、指定リリースの*.tar.gzファイルを拾ってきて展開すれば十分なケースではgitのインストールすら避けるのが良いでしょう。

繰り返しとなりますが、チーム用などに開発用環境を用意する際は別です。

特に事情がなければディストリビューションのバイナリ配布物を利用する

ソフトウェアパッケージのビルドには多くの追加パッケージが必要です。gcc、libstdc++6-dev、make、autotools、cmakeなどなど。build-essentialをえいやっと追加すると一気にディスク容量が膨らみます。

というわけで、もし特殊な事情がなければ、なるべくディストリビューションの提供するバイナリ配布物を使うようにDockerfileを記述すべきです。

しかし、ディストリビューションの公式パッケージに入っていないものやバージョンが古いもの・互換性のないものなどについては仕方ありません。なるべく追加容量が最小限で済むように留意しつつ、パッケージをインストールしましょう。

イメージビルド中の多階層ディレクトリに対するchownを避ける

これもDockerの構造がステージごとにファイルシステム状態を記録することに関連します。このblogでは、特定ディレクトリへのchownをビルドフェーズでおこなったところ、72MBもの容量増につながったという話が紹介されています。

代替策として、chownをCOMMANDでの起動シーケンスへと移動したということです。なかなか難しいですね。

ONBUILDを利用して一部処理をイメージ実行時へ逃がす

利用できるシーンが一定限られますが、例えば「あるシステムの実行のために大量の静的ファイル(しかもそれなりに頻繁な更新がおこなわれる)を拾ってくる必要がある」といった場合に有効です。

コンテナの一部として頻繁な更新のおこなわれるファイル群を利用する場合、それらが更新される都度Docker Hubでのビルドをおこなうのはあまり効率的と言えません。

そこで用意されているのがONBUILDコマンドです。RUNコマンドがイメージ生成時に実行されるコマンドであるのに対して、ONBUILDコマンド(マニュアル)は当該処理をコンテナ生成時まで後回しするものです。

番外編: 既存の巨大イメージをダイエットする

基本的にはDockerfileを編集してイメージ作り工程を改善するお話ですが、仮にDockerfileへアクセスできなくてもとれる策がこれです(これも上記ページで紹介されています)。

実行中のコンテナを指定して

docker export <container id> | docker import - <new image name>

で、イメージのビルド時にステージごとに生成されたレイヤがごっそり統合されます。結果として、ベースイメージからの差分保持すらされなくなるため、場合によっては当該イメージ単体のサイズは増えるかもしれません。

他方、パフォーマンス面では実行時にアクセスするfsレイヤを減らせるのでファイルI/O面は多少有利になるかもしれません。

メリットとデメリットを把握して利用する必要のある策です。

1  
ビルドツール群まで削除対象にするという発想は、まさに目からウロコでした。バイナリから確保すればたしかに必要でなくなります‌​ね。 加えて、chownをすると容量増に繋がるというのは結構衝撃的ですね。とりあえず、ONBUILDで逃がせるものは逃がしてみ‌​たいと思います。 不要な中間ファイルの削除の項目で思い出したのですが、 (ご存知かもしれませんが)パッケージインストール後、apt-get cleanをするといいという記事をどこかでみました。 自分用メモという意味も含め、書き残しておきます。 – j138 14年12月11日 1:31