先日のCNDT2022でdocker-slimについて触れたセッションがあり、これはええやないのということで試してみた。
今回試したイメージは ruby:3
です。
$ docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" |grep 'ruby:3
ruby:3 893MB
もとのサイズが 893MB
です。こいつにdocker-slimを何も考えずにかませると、
% docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" |grep -e ruby
ruby.slim:latest 22.3MB
ruby:3 893MB
893MB → 22.3MB ヤバすぎますね!!!!!!
ただ、この話は少々複雑です。
Rubyに同梱されているbundlerのバージョンをみてみます。まずは ruby:3
から。
% docker run ruby:3 bundle version
Bundler version 2.3.7 (2022-11-25 commit unknown)
問題なく実行できます。
続いて、slimイメージ。
% docker run ruby.slim:latest bundle version
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "bundle": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
なんということでしょう、bundleコマンドがありません。パスを調べてみます。
% docker run ruby:3 which bundle
/usr/local/bin/bundle
/usr/local/bin/bundle
ですね。これをslimイメージでもみてみましょう。
% docker run ruby.slim:latest ls /usr/local/bin
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "ls": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
なんと、lsすらありません。つまりdokcer-slimは不要なバイナリなどのファイルを削除してしまう挙動をします。
この動作を避けるには、--preserve-path
オプションで削除対象外とするパスを指定する必要があります。
% docker-slim build --http-probe=false --preserve-path /usr/local/bin/ --preserve-path /usr/local/lib ruby:3
こうすると、若干サイズは増えますが、bundleは実行が可能です。
% docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" |grep -e ruby
ruby.slim:latest 58.7MB
ruby:3 893MB
% docker run ruby.slim:latest bundle version
Bundler version 2.3.7 (2022-11-25 commit unknown)
ソースをざっくり読んだところ、docker-slim自体がデフォルトで除外してくれるファイルやパスもあるのですが、基本的にはコンテナイメージに合わせてコマンドライン引数や、ファイルを利用してホワイトリストを定義する必要があるようです。
残す必要があるファイルをホワイトリスト的に定義していく必要があるので、手持ちのイメージにローラー的にかけるのは厳しいと思いますが、Goのようにワンバイナリでだいたい動くようなものとは非常に相性が良さそうに思います。
既存のものに対して頑張るモチベーションはあまりないのだけど、これから新規に起こすものにはちょっと使ってみようかなと思っている今日このごろです。