[Docker] scratchイメージとstaticライブラリ

2018年9月25日火曜日

C Docker gcc linux

scratchイメージ

最小限の素のDockerイメージを自分で作る場合にはscratchイメージを使う。これをちょっと試してみた。
https://hub.docker.com/_/scratch/

サンプルプログラム

普通にCのhello worldを作ると。
main.c
#include <stdio.h>

int main(void) {
    printf("hello.\n");
    return 0;
}

$ gcc -Wall -o main main.c

Dockerのファイルは以下のようにする。
docker-compose.yml
version: "2"
services:
  app:
    build:
      context: .
    command: /main
Dockerfile
FROM scratch
COPY ./main /main

docker-composeで起動。
$ docker-compose up
Creating network "scratch_default" with the default driver
Building app
Step 1/2 : FROM scratch
 ---> 
Step 2/2 : COPY ./main /main
 ---> 885e8567c48d
Successfully built 885e8567c48d
Successfully tagged scratch_app:latest
WARNING: Image for service app was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating scratch_app_1
Attaching to scratch_app_1
app_1  | standard_init_linux.go:185: exec user process caused "no such file or directory"
scratch_app_1 exited with code 1
$ 
...しても、standard_init_linux.go:185: exec user process caused "no such file or directory" で、エラーになってしまう。

依存しているライブラリを見てみよう。
$ ldd main
    linux-vdso.so.1 (0x00007ffda71df000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f9e2f1fd000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f9e2f5a2000)
依存しているライブラリのファイルもコピーする手もあるけど、staticライブラリをリンクしてしまおう。

staticライブラリをリンクする

staticライブラリをリンクするには-staticオプションを付ける。
lddで確認すると、実行ファイルが動的リンクではないことがわかる。
$ gcc -Wall -static -o main main.c
$ ldd main
    動的実行ファイルではありません
※-staticオプションをつけると、エラーが出る場合はglibcのstaticライブラリが入っていない可能性があるので、glibc-staticを入れよう。

docker-composeで、再度起動する。先ほど一度イメージファイルを作成しているので、再度イメージファイルを作成するように今度は明示的に --build オプションをつけている。
$ docker-compose up --build
Building app
Step 1/2 : FROM scratch
 ---> 
Step 2/2 : COPY ./main /main
 ---> 8bd665fe0ffc
Successfully built 8bd665fe0ffc
Successfully tagged scratch_app:latest
Recreating scratch_app_1
Attaching to scratch_app_1
app_1  | hello.
scratch_app_1 exited with code 0
$ 
イメージファイルを一から作ることはあまりないかもしれないけど、意外と手軽にできそう。