1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Docker】docker imageの大きさを小さくする (その1)

Last updated at Posted at 2021-08-23

はじめに

Docker を使っていますが、イメージの大きさを削減しなくてはならない場面が出てきました。
今回その1にしたのは、後日その2がある予定なので。^^)/

C言語で書いたプログラム

今まで、Linuxマシンで動かしていたものをdocker image にするには、基本的に

  1. ソースをコピーする
  2. build する
  3. コンテナ起動時に呼び出して使えるようにする

というのをDockerfile の中に記述していました。単純ですがこれで動いていたので、今まで良しとしてきました。なのですが、よく考えると、これをコンテナとして実行するときには、実行ファイルと動的に読み出すライブラリだけあれば十分なはずです。コンパイラ、静的ライブラリ、ヘッダファイルなどは、build するときにだけ必要です。

ビルド環境をイメージに含めない

今回、調べたら、分かり易いが説明がいくつもありました。

↑これで使われているサンプルのプログラムは、こちらにあります。

これはGO言語での例ですが、分かり易く、そのまま動かすことができました。勉強になりました。感謝感激です。

以下は、私なりの理解です。私はC言語で動かしています。

  1. 一度docker image の中で動く実行ファイルを作る。これはコンテナとしてはrun させることはなく、実行ファイルを作るためだけにdocker build される
  2. コンテナとして run するために使うイメージを作る。ここでは、必要なbase image に、先の作った実行ファイルをコピーする。実行物をコピーするだけなので、build に必要な環境は含まれないので、image の大きさが小さくてすむ。
  3. 以前は、dokcer cp コマンドを使って実行ファイルをbuild コンテナから取り出していたようだが、昨今では、docker build 実行時にbuild container 内でコピーすることができる。

ということのようです。二つのコンテナを作っても良いのですが、これを一つのDockerfile で行うことができます。次のサイトは、build の高速化の説明ですが、前半にmulti-stage build をC言語を例に行っていたので、参考になりました。

実行例

用意するもの

種も仕掛けもありません。今回の実験では、ファイルは3つ。

├── Dockerfile.multi-stage
├── Dockerfile.single-stage
└── hello.c

C言語のhello world。心が和む。

hello.c
#include <stdio.h>
int main()
{
  printf("hello.\n");
  return 0;
}

普通のDockerfile。コピーしてコンパイルする。build-essential をapt-get する。

single-stage.Dockerfile
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends gcc build-essential

WORKDIR /root
COPY hello.c .
RUN gcc -o helloworld hello.c
CMD ["./helloworld"]

それから、今回の目玉のmulti-stage でbuild する Dockerfile。WORKDIR を経由して、実行ファイルだけコピーしているところがポイント。

multi-stage.Dockerfile
# This is the first image:
FROM ubuntu:18.04 AS compile-image
RUN apt-get update
RUN apt-get install -y --no-install-recommends gcc build-essential

WORKDIR /root
COPY hello.c .
RUN gcc -o helloworld hello.c

# This is the second image.
FROM ubuntu:18.04 AS runtime-image

COPY --from=compile-image /root/helloworld .
CMD ["./helloworld"]

ビルドして大きさを比較してみる

これをいざビルドしてみよう。

$ docker build -f single-stage.Dockerfile -t c-hello .
$ docker build -f multi-stage.Dockerfile -t c-hello2 . 

image の大きさを比べてみると、、、

$ docker
 images
REPOSITORY                    TAG               IMAGE ID       CREATED
             SIZE
c-hello2                      latest            c8470180dd3f   5
seconds ago        63.1MB
c-hello                       latest            0db6a6cf73e5   About a
minute ago   295MB

結構差がありますね。^^; もちろん、動きます。

$ docker run --rm c-hello2
hello.

まとめ

とりあえず、Cをソースからビルドするdocker image を作る時、image size を小さくする方法を一つ理解した。

  • build するときは build-essentials を apt でインストールして使う。
  • Dockerfileの途中で、build が終わった後であらためてbase image を定義し、実行用のイメージ作成には必要なバイナリだけコピーしてくる。

今後

実は python ではどうなるのじゃ、ということを調べています。同じように考え方で行けそうなのですが、動作確認できたらメモします。ふー。

2021/08/23 から日付が変わって0:48

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?