LoginSignup
31
26

More than 5 years have passed since last update.

distrolessイメージを使って、ランタイムDockerイメージを作ってみる

Last updated at Posted at 2018-07-18

distrolessとは?

Googleが公開している、ランタイム用のDockerイメージです。

なぜ使うか?

Dockerはプロダクション環境にも導入されるようになりました。

プロダクション環境では脆弱性対応などをする必要があります。
デプロイされるDockerイメージをアプリケーション実行に必要なものだけに制限することで、このような間接的な作業を減らすことが可能です。

distrolessイメージはこのような要望に対応した、アプリケーションランタイムのみに特化したDockerイメージです。

実際にイメージに入っているのは、gcr.io/distroless/baseの場合、

  • glibc
  • libssl
  • openssl
  • ca-certificates
  • A /etc/passwd entry for a root user
  • A /tmp directory

のみです。

nodejsイメージなどは、上記に追加で各ランタイム用のバイナリが含まれるようです。

使ってみる

distrolessイメージを使ったランタイムイメージを作成する

https://github.com/GoogleContainerTools/distroless
のexampleを元にnodejsで試してみました。

以下のような Dockerfile が格納されています。

FROM node:8.9.1 AS build-env
ADD . /app
WORKDIR /app

FROM gcr.io/distroless/nodejs
COPY --from=build-env /app /app
WORKDIR /app
CMD ["hello.js"]

ビルドステージ(最初3行)とそのアウトプットを distrolessイメージにコピーするステージ(最後の4行)に分かれています。

distrolessイメージの話というよりマルチステージビルドの話になりますが、この記述の意図は、「アプリのビルド時だけに必要な依存パッケージは最終イメージに持ち込ませない」だと思います。

このDockerfileを使って、
distrolessイメージをベースとしたDockerイメージをビルドしてみます。

$ docker build . -t nodejs_distroless                                                                                  水  7/18 22:09:30 2018
Sending build context to Docker daemon  7.168kB
Step 1/7 : FROM node:8.9.1 AS build-env
8.9.1: Pulling from library/node
85b1f47fba49: Pull complete
ba6bd283713a: Pull complete
817c8cd48a09: Pull complete
47cc0ed96dc3: Pull complete
8888adcbd08b: Pull complete
6f2de60646b9: Pull complete
51fa8867e10f: Pull complete
3de546fb9d8f: Pull complete
Digest: sha256:552348163f074034ae75643c01e0ba301af936a898d778bb4fc16062917d0430
Status: Downloaded newer image for node:8.9.1
 ---> 1934b0b038d1
Step 2/7 : ADD . /app
 ---> edaf827024d3
Step 3/7 : WORKDIR /app
Removing intermediate container 1712ca1226a1
 ---> 26d537ccf985
Step 4/7 : FROM gcr.io/distroless/nodejs
latest: Pulling from distroless/nodejs
57752e7f9593: Pull complete
ba7c544469e5: Pull complete
fe1a8dd285c0: Pull complete
Digest: sha256:ed997b713028c133799c41c2401e5d77ba1973876e92c55d1d67b6a0b68e9c29
Status: Downloaded newer image for gcr.io/distroless/nodejs:latest
 ---> a853ae078c7b
Step 5/7 : COPY --from=build-env /app /app
 ---> b3c68eb49cc5
Step 6/7 : WORKDIR /app
Removing intermediate container 79aa5baa396d
 ---> b6f4f9fd66d3
Step 7/7 : CMD ["hello.js"]
 ---> Running in 4dfbc310729f
Removing intermediate container 4dfbc310729f
 ---> ccb158736e44
Successfully built ccb158736e44
Successfully tagged nodejs_distroless:latest

実際どうなのか

イメージサイズ

node Dockerイメージを使ってビルドした結果と比較します。

ベースのイメージ イメージサイズ
node:8.9.1 676MB
node:8.9.1-alpine 67.7MB
gcr.io/distroless/nodejs:latest 75.1MB

結果的に、alpineの方が容量が少なくなりましたが、
ほとんど同レベルとなっています。

ログインしようとしてみる

$ docker run --rm -it --entrypoint /bin/bash nodejs_distroless 
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown.
$ docker run --rm -it --entrypoint /bin/sh nodejs_distroless 
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"/bin/sh\": stat /bin/sh: no such file or directory": unknown.

できませんでした。

まとめ

最初タイトルを「最小のランタイム用」としようと思っていましたが、
nodejsはalpineよりもサイズが大きくなってしまいました笑
(Golangでやってみればよかった)

現状は以下のイメージが公開されています。

  • gcr.io/distroless/base (Golangなどバイナリでコンパイルされたものの実行環境)
  • gcr.io/distroless/java (openjdk8ベース)
  • gcr.io/distroless/cc (Rust, D言語用)
  • gcr.io/distroless/python2.7
  • gcr.io/distroless/python3
  • gcr.io/distroless/nodejs
  • gcr.io/distroless/java/jetty
  • gcr.io/distroless/dotnet

このうち、base以外はまだ、プロダクションレディのようです。
※java, ccについては、GitレポジトリのReadmeからはどちらかわかりませんでした。。

31
26
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
31
26