Help us understand the problem. What is going on with this article?

Alpine Linux で Docker イメージを劇的に小さくする

More than 3 years have passed since last update.

Docker イメージを小さく作るテクニックって、いろいろありますよね。不要なファイルやディレクトリを削除したり、複数の RUN 命令をひとつにまとめたりなどなど。

ところが、ベースイメージに Alpine Linux を使う(FROM alpine とする)と、Docker イメージのサイズを 劇的に小さくできる ことがわかりました。

いままで、Docker イメージのサイズを小さくするために、ちまちまとやってきたことは、なんだったんだろうという感じです。まあ、それはそれで組み合わせて使いますが . . . なんとも . . . ねえ(笑)

Alpine Linux とは

  • Alpine Linux は、セキュアで軽量な Linux ディストリビューション
  • musl libcBusyBox をベースに構成されている
  • 組込み系に適した Linux ディストリビューション
  • パッケージ管理は、APK と呼ばれる独自のシステムを使用

実際どれくらい小さくなるのか

Ruby を組み込んだ「Ubuntu ベースの Docker イメージ」と「Alpine ベースの Docker イメージ」で、そのサイズを比較してみました。

Ubuntu ベース、Alpine ベースそれぞれの Dockerfile は、次のとおりです。

ubuntu-ruby.dockerfile
FROM ubuntu:xenial-20160525
RUN apt-get update && apt-get install -y ruby && rm -rf /var/lib/apt/lists/*
alpine-ruby.dockerfile
FROM alpine:3.4
RUN apk --update add ruby && rm -rf /var/cache/apk/*

これを、次のコマンドで、それぞれビルドします。

docker build -f ubuntu-ruby.dockerfile -t ubuntu-ruby .
docker build -f alpine-ruby.dockerfile -t alpine-ruby .

ちゃんと動くか動作を確認しておきます。

docker run --rm ubuntu-ruby ruby -e 'puts "hello, world"'
docker run --rm alpine-ruby ruby -e 'puts "hello, world"'

それぞれ、hello, world と表示されれば、OK です(というか、表示されます)。

docker images コマンドで、サイズを確認すると . . .

$ docker images
REPOSITORY                         TAG                 IMAGE ID            CREATED             SIZE
alpine-ruby                        latest              1ac582156fbc        28 seconds ago      20.39 MB
ubuntu-ruby                        latest              b90dadde262c        50 seconds ago      156.9 MB

なんと!!! Alpine Linux ベースの Docker イメージは、20.39MB に!!!
Ubuntu ベースの Docker イメージは、156.9MB ですから、この差はデカイです!

この差はなにか

ベースイメージを変えただけで、なぜ、こんなにも差が出るのでしょうか。

まあ、答えは簡単ですよね。ベースイメージの大きさの差がそのまま結果に表れているということですね。

ベースイメージでよく使われていると思われる Ubuntu、Debian および CentOS と Alpine で、その大きさを比較してみました(2016/06/04 時点)。

REPOSITORY                         TAG                 IMAGE ID            CREATED             SIZE
alpine                             3.4                 f70c828098f5        32 hours ago        4.799 MB
centos                             7                   904d6c400333        34 hours ago        196.8 MB
ubuntu                             xenial-20160525     2fa927b5cdd3        7 days ago          122 MB
debian                             8.4                 1742affe03b5        11 days ago         125.1 MB

Alpine のサイズは、驚きの 4.799MB !!!

Ubuntu、Debian、CentOS がいずれも 100MB を超えているので、その差は本当に大きいですね。

ただ、あまりの小ささに少し不安になりますよね。本当に大丈夫なのかと。なので、いくつかの Docker イメージを作って、試してみました。本格的に使用しているわけではありませんが、まずまずちゃんと動いているようです。

そのいくつか試した中から、Nginx の例を載せておきます。参考にどうぞ。

Nginx サンプル

パッケージのインストールは、APK を使います。APK は、Alpine Linux のパッケージ管理システムです。APK は、同種の APT や Yum と同じような感じで使えます。次の Dockerfile のサンプルで、APK の使い方を確認してみましょう。

なお、利用できるパッケージの一覧は、Alpine Linux package index で確認できます。

Dockerfile

ここでは、Nginx をソースからコンパイルしてインストールする方法を紹介します。APK は、Nginx ソースの入手と、コンパイル&インストールに必要なパッケージのインストールで使用しました。

(APK で、Nginx をインストールすると、stable 版の v1.8.0 がインストールされるようです。より新しいバージョンをインストールしたい場合や、欲しいパッケージが用意されていない場合は、このソースからコンパイルしてインストールする方法が参考になるかと思います。)

alpine-nginx.dockerfile
FROM alpine:3.4

ENV NGINX_VERSION 1.11.1

RUN apk --update add pcre-dev openssl-dev \
  && apk add --virtual build-dependencies build-base curl \
  && curl -SLO http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \
  && tar xzvf nginx-${NGINX_VERSION}.tar.gz \
  && cd nginx-${NGINX_VERSION} \
  && ./configure \
       --with-http_ssl_module \
       --with-http_gzip_static_module \
       --prefix=/usr/share/nginx \
       --sbin-path=/usr/local/sbin/nginx \
       --conf-path=/etc/nginx/conf/nginx.conf \
       --pid-path=/var/run/nginx.pid \
       --http-log-path=/var/log/nginx/access.log \
       --error-log-path=/var/log/nginx/error.log \
  && make \
  && make install \
  && ln -sf /dev/stdout /var/log/nginx/access.log \
  && ln -sf /dev/stderr /var/log/nginx/error.log \
  && cd / \
  && apk del build-dependencies \
  && rm -rf \
       nginx-${NGINX_VERSION} \
       nginx-${NGINX_VERSION}.tar.gz \
       /var/cache/apk/*

VOLUME ["/var/cache/nginx"]

EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]

2016/05/22 変更: alpine:3.2alpine:3.3NGINX_VERSION 1.9.7NGINX_VERSION 1.10.0
2016/06/04 変更: alpine:3.3alpine:3.4NGINX_VERSION 1.10.0NGINX_VERSION 1.11.1

APK コマンドの解説:

  • apk add: 指定したパッケージをインストールします。
    • --update オプション: パッケージリストを更新します。最初の apk add 時に必要です。
    • --virtual オプション: インストールするパッケージ群に名前をつけます。apk del で使用します。
      この例では、build-base と curl をひとつのグループとして扱い、build-dependencies と命名しました。
  • apk del: 指定したパッケージをアンインストールします。
    この例では、apk add--virtual オプションで命名した build-dependencies を指定しました。これにより、build-dependencies に紐付いた build-base と curl をアンインストールします。

使い方の例

どこか適当なディレクトリで、上記 Dockerfile を alpine-nginx.dockerfile というファイル名で保存して、次のコマンンドを実行します。最後に、'hello, world' と表示されれば成功です。

docker build -f alpine-nginx.dockerfile -t nginx .
echo 'hello, world' > index.html
docker run -d -p 8080:80 -v $(pwd):/usr/share/nginx/html nginx
curl http://$(docker-machine ip default):8080

なお、Linux 環境の場合は、最後の curl コマンドは、curl http://localhost:8080 に読み替えてください。

まとめ

作成する Docker イメージのベースイメージに、Alpine Linux を指定すると、Docker イメージのサイズを劇的に小さくできることがわかりました。

これは、試していて実感したのですが、Docker イメージのサイズが小さいと、docker pulldocker pushdocker build も超高速です。これは、嬉しかったですね。

ただし、どのような Docker イメージにも適用できるかと問われると、なんとなくですが難しいケースも多々ある気がします。とはいえ、試して見る価値は、十分にあると思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away