Dockerのscratchイメージを探検する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Amazon EC2 Container Service (ECS): ECSエージェントの動作を確認するを書いている中で、scratchイメージの存在を知りました。

This image is most useful in the context of building base images or super minimal images

とのことで、超最小化されたベースイメージのようです。超最小というだけあってshさえ入っておらず、コンテナの中にシェルログインしようとしても入れません。

$ sudo docker run -it scratch /bin/sh
exec: "/bin/sh": stat /bin/sh: no such file or directoryFATA[0000] Error response from daemon: Cannot start container f7eb41a5e71f6c9357267ae572f3e990698c2ee54854dd362fefec88a29f2108: exec: "/bin/sh": stat /bin/sh: no such file or directory

ということで、このscrachイメージの中にログインできるようにして、中身を確認してみました。

やってみた

実行した環境はAmazon Linuxです。

要は、scrachイメージにshコマンドを追加したイメージを作って、コンテナ起動すれば良い訳です。ただ単純shコマンドをコピーしても、依存している共有ライブラリが無いと動きません。なので/bin/shが依存している共有ライブラリをlddコマンドで確認します。

$ ldd /bin/sh
	linux-vdso.so.1 =>  (0x00007fff3bffe000)
	libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007f934d17f000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f934cf7a000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f934cbd5000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f934d3a9000)

作業用ディレクトリを作り、shコマンドとその依存している共有ライブラリをコピーします。

$ mkdir work;cd work
$ cp /bin/sh ./
$ cp /lib64/libtinfo.so.5 ./
$ cp /lib64/libdl.so.2 ./
$ cp /lib64/libc.so.6 ./
$ cp /lib64/ld-linux-x86-64.so.2 ./
$ ls
ld-linux-x86-64.so.2  libc.so.6  libdl.so.2  libtinfo.so.5  sh

scratchイメージにshコマンドを追加するためのDockerfileを作成します。

$ vi Dockerfile
FROM scratch
COPY ./sh /bin/sh
COPY ./libtinfo.so.5 /lib64/libtinfo.so.5
COPY ./libdl.so.2 /lib64/libdl.so.2
COPY ./libc.so.6 /lib64/libc.so.6
COPY ./ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
CMD ["/bin/sh"]

docker buildします。

$ sudo docker build -t local/sh .
Sending build context to Docker daemon 3.212 MB
Sending build context to Docker daemon
Step 0 : FROM scratch
 ---> 511136ea3c5a
Step 1 : COPY ./sh /bin/sh
 ---> Using cache
 ---> d888ba3ab54c
Step 2 : COPY ./libtinfo.so.5 /lib64/libtinfo.so.5
 ---> Using cache
 ---> 391272660fd9
Step 3 : COPY ./libdl.so.2 /lib64/libdl.so.2
 ---> Using cache
 ---> e612a1cd98af
Step 4 : COPY ./libc.so.6 /lib64/libc.so.6
 ---> Using cache
 ---> 1197f1569133
Step 5 : COPY ./ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
 ---> Using cache
 ---> b8b023b3f1dd
Step 6 : CMD /bin/sh
 ---> Using cache
 ---> d64311c33f95
Successfully built d64311c33f95

これでshコマンドを含めたscratchイメージが出来ました。

$ sudo docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
local/sh               latest              d64311c33f95        33 seconds ago      3.206 MB

ではコンテナ起動します!

$ sudo docker run -it local/sh /bin/sh
sh-4.1#

はい、ログイン出来ましたね!

しかしlsコマンドもありません...

sh-4.1# ls
sh: ls: command not found

仕方がないのでechoで代用します。

sh-4.1# echo *
bin dev etc lib64 proc sys

sh-4.1# cd /sys
sh-4.1# echo *
block bus class dev devices firmware fs hypervisor kernel module power

sh-4.1# cd /etc
sh-4.1# echo *
hostname hosts mtab resolv.conf

本当に最小限のものしか入っていないようですね。そんなわけで、scratchイメージの内容が見えるようになりました!

さいごに

Docker関連はやってもやっても新しい発見ばかりです。本当はもっとECSに特化して勉強するつもりだったのですが、すっかり横道に逸れました。でも楽しいです!