独自 Hello world の Docker イメージをビルドする

さくらの夕べ Tech Night #2 Online のアーカイブで、2つ目のセッション「いまさら聞けないDockerの”hello-world”イメージ」を視聴してHello World の Docker イメージを自作してみようと思い試してみました。

Hello World アプリを作成する

まず、Hello world を表示する何かを作らないといけない。

最小構成にするためベースとなるイメージを scratch にしたい。
つまり /bin/sh が動かないのでシェルスクリプトではなくバイナリーを作らないといけない。

Hello World を C 言語で書く。久しぶりに C を書いた。

1
2
3
4
5
#include <stdio.h>

int main() {
printf("Hello, Wordl!\n");
}

ビルドする。

1
# gcc -o hello hello.C

問題なくビルドできたので、実行してみる。

1
2
$ ./hello
Hello, Wordl!

Hello World の Docker イメージを作成する

最小構成でイメージを作成したいので、scratch を使用することにした。

1
2
3
FROM scatch
COPY hello /root/hello
CMD ["/root/hello"]

作成した Dockerfiele を元に Docker イメージをビルドする。

1
2
3
4
5
6
7
8
9
10
11
12
$ sudo docker build --no-cache -t hello ./
Sending build context to Docker daemon 12.29kB
Step 1/3 : FROM scratch
--->
Step 2/3 : COPY hello /root/hello
---> f9a1fd8b89f6
Step 3/3 : CMD ["/root/heセッションセッション
---> Running in ab1526bd34ee
Removing intermediate container ab1526bd34ee
---> f250b9beefb0
Successfully built f250b9beefb0
Successfully tagged hello:latest

コンテナを起動してみる。

1
2
$ sudo docker run --rm  hello
standard_init_linux.go:211: exec user process caused "no such file or directory"

あれ、動かない!?

原因調査

実行ファイル自体は COPY されているので、”no such file or directory” となるのは、実行ファイル hello を動かすために必要なファイルが他にあるのだろう。
昔の記憶を頼りに動的リンクするライブラリーが必要なのだろうと調べてみる。

1
2
3
4
# ldd hello
linux-vdso.so.1 (0x00007ffebb6da000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f360eeb4000)
/lib64/ld-linux-x86-64.so.2 (0x00007f360f455000)

やはり、Docker コンテナ内で実行するとライブラリーが存在しないので、エラーが発生するようだ。

対処方法

不足しているライブラリーを Docker イメージに COPY する方法もあるが、今回は最小構成の Docker イメージを作成したいので実行ファイルにライブラリーを含めてしまうことにする。

1
2
3
$ gcc -static -o hello hello.c
$ ldd hello
not a dynamic executable

今度は必要なライブリーがすべて含まれた実行ファイルが作れた。

再挑戦

再度、Docker イメージを作成する。

1
2
3
4
5
6
7
8
9
10
11
12
$ sudo docker build --no-cache -t hello ./
Sending build context to Docker daemon 814.1kB
Step 1/3 : FROM scratch
--->
Step 2/3 : COPY hello /root/hello
---> 382b73c148a3
Step 3/3 : CMD ["/root/hello"]
---> Running in 24b58e43490e
Removing intermediate container 24b58e43490e
---> 358a4456f767
Successfully built 358a4456f767
Successfully tagged hello:latest

そして、実行する。

1
2
$ sudo docker run --rm  hello
Hello, Wordl!

動いた!