2. 本日の流れ
● 今日のゴール
● Dockerfileの基礎
● ベストプラクティスを振り返る
● まとめ
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
3. 林 如弥(Yukiya Hayashi) @morihaya55
● 好きなDockerfile
○ https://github.com/moby/moby/blob/ma
ster/Dockerfile
○ 2018-02-18のコミット“Updates the
Dockerfile to use multi-stage”で激変!
簡単な自己紹介
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
12. Dockerfileのベストプラクティスとは?
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● docs.docker.comで公開されているドキュメント
(https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)
● 良いDockerfileを書くための指南書
● “26分”で読めるコンパクトな量(私は無理)
“Estimated reading
time:26 minutes”
13. Dockerfileのベストプラクティスとは?
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 以下の4章で構成
○ General guidelines and recommendations
○ Dockerfile instructions
○ Examples for Official Repositories
○ Additional resources:
14. Dockerfileのベストプラクティスとは?
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 以下の4章で構成(雑な日本語訳)
○ 一般的なガイドラインと、使い方推奨
○ 各命令語についての使い方推奨
○ オフィシャルなサンプル集
○ 追加情報へのリンク集
15. Dockerfileのベストプラクティスとは?
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 以下の4章で構成(雑な日本語訳)
○ 一般的なガイドラインと、使い方推奨
○ 各命令語についての使い方推奨
○ オフィシャルなサンプル集
○ 追加情報へのリンク集
内容の90%はこの2章分
16. Dockerfileのベストプラクティスとは?
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 以下の4章で構成(雑な日本語訳)
○ 一般的なガイドラインと、使い方推奨
○ 各命令語についての使い方推奨
○ オフィシャルなサンプル集
○ 追加情報へのリンク集 本セッションではこの2章から、
個人的に良かった物を抜粋して
お話します
24. 3. Pipe Dockerfile through stdin
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● Dockerfileを作成しなくても、パイプラインで標準
出力からdocker buildへコマンドを渡せる
● さらにリモートのビルドコンテクストにも標準出力か
らDockerfileを渡せる
25. 3. Pipe Dockerfile through stdin - 2
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● Dockerfileを作成しなくても、パイプラインで標準
出力からdocker buildへコマンドを渡せる
docker build -t foo . -f-<<EOF
FROM busybox
RUN echo "hello world"
COPY . /my-copied-files
EOF Dockerfileを作らないでOK!
26. 3. Pipe Dockerfile through stdin - 3
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● さらにリモートのビルドコンテクストにも標準出力か
らDockerfileを渡せる
docker build -t foo https://github.com/thajeztah/pgadmin4-docker.git
-f-<<EOF
FROM busybox
COPY LICENSE config_distro.py
/usr/local/lib/python2.7/site-packages/pgadmin4/
EOF
config_local.pyに公
式はなってるけど間違
い(PR済み)
27. 4. Exclude with .dockerignore
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 余計なファイルをイメージに入れないため
に.dockerignoreファイルを使用する
● .gitignoreのDockerfile版(書式も同じ)
*/temp*
*/*/temp*
temp?
28. 5. Use multi-stage builds
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● Dockerfile革命的な機能であるマルチステージビ
ルドを使う
● Go言語のような、Go言語としてのビルドに必要な
ファイル群と、実行に必要なGoバイナリがきっちり
分離できるような用途に最適
29. 5. Use multi-stage builds - 2
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
FROM golang:1.9.2-alpine3.6 AS build
# 必要なツールをインストール
RUN apk add --no-cache git
RUN go get github.com/golang/dep/cmd/dep
COPY Gopkg.lock Gopkg.toml /go/src/project/
WORKDIR /go/src/project/
# 関連ライブラリをインストール
RUN dep ensure -vendor-only
# Goビルドを実行(バイナリが生成される)
COPY . /go/src/project/
RUN go build -o /bin/project
# This results in a single layer image
FROM scratch
COPY --from=build /bin/project /bin/project
ENTRYPOINT ["/bin/project"]
CMD ["--help"]
30. 5. Use multi-stage builds - 3
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
FROM golang:1.9.2-alpine3.6 AS build
# 必要なツールをインストール
RUN apk add --no-cache git
RUN go get github.com/golang/dep/cmd/dep
COPY Gopkg.lock Gopkg.toml /go/src/project/
WORKDIR /go/src/project/
# 関連ライブラリをインストール
RUN dep ensure -vendor-only
# Goビルドを実行(バイナリが生成される)
COPY . /go/src/project/
RUN go build -o /bin/project
# This results in a single layer image
FROM scratch
COPY --from=build /bin/project /bin/project
ENTRYPOINT ["/bin/project"]
CMD ["--help"]
ここまでがビルド
31. 5. Use multi-stage builds - 4
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
FROM golang:1.9.2-alpine3.6 AS build
# 必要なツールをインストール
RUN apk add --no-cache git
RUN go get github.com/golang/dep/cmd/dep
COPY Gopkg.lock Gopkg.toml /go/src/project/
WORKDIR /go/src/project/
# 関連ライブラリをインストール
RUN dep ensure -vendor-only
# Goビルドを実行(バイナリが生成される)
COPY . /go/src/project/
RUN go build -o /bin/project
# This results in a single layer image
FROM scratch
COPY --from=build /bin/project /bin/project
ENTRYPOINT ["/bin/project"]
CMD ["--help"]“build”と名付けたステージで
生成したバイナリを、実行用
のイメージへCOPY
32. 6. Don’t install unnecessary packages
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 不必要なパッケージは入れない
● net-toolsとかvimとか”あると便利”なだけで、必須
でなければ入れない
(入れたい気持ちはわかるけど)
33. 7. Decouple applications
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 1コンテナ=1アプリケーションが原則
● DB、キャッシュ、WEBはちゃんと別コンテナに分け
ること
● ただし1コンテナあたり1プロセスに制限してしまう
と、apacheのようなセッション単位でプロセス増や
すソフトウェアもあるから注意
34. 8. Minimize the number of layers
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● レイヤ数は可能な限り減らす
● RUN, COPY, ADDだけがレイヤを増やすので、こ
れらの命令語を使用するときに意識する
○ LABEL等もレイヤ作るけどサイズに影響はしな
い
● マルチステージビルド使ってね
35. 8. Minimize the number of layers - 2
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● レイヤ数とレイヤの各サイズは”docker history”コ
マンドで確認ができる
$ docker history postgres:10
IMAGE CREATED CREATED BY SIZE COMMENT
6eb6c50a02e7 4 days ago /bin/sh -c #(nop) CMD ["postgres"] 0B
<missing> 4 days ago /bin/sh -c #(nop) EXPOSE 5432/tcp 0B
<missing> 4 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B
….
<missing> 2 weeks ago /bin/sh -c #(nop) ENV GOSU_VERSION=1.10 0B
<missing> 2 weeks ago /bin/sh -c set -eux; groupadd -r postgres -… 329kB
<missing> 2 weeks ago /bin/sh -c set -ex; if ! command -v gpg > /… 10.2MB
<missing> 2 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ADD file:dab9baf938799c515… 55.3MB
36. 8. Minimize the number of layers - 3
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● GitHub orisano/dlayer でさらに詳細もみれる
$ docker save postgres:10 | dlayer -n 100 | less
===================================================================================================
55 MB $ #(nop) ADD file:dab9baf938799c515ddce14c02f899da5992f0b76a432fa10a2338556a3cb04f in /
====================================================================================================
2.0 MB usr/bin/perl
1.8 MB usr/lib/x86_64-linux-gnu/libdb-5.3.so
1.8 MB usr/lib/x86_64-linux-gnu/perl-base/unicore
1.8 MB usr/lib/x86_64-linux-gnu/libapt-pkg.so.5.0.1
1.7 MB lib/x86_64-linux-gnu/libc-2.24.so
1.6 MB usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22
1.5 MB usr/lib/locale/C.UTF-8/LC_COLLATE
1.1 MB lib/x86_64-linux-gnu/libgcrypt.so.20.1.6
...
37. 9. Sort multi-line arguments
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 複数行の引数はソートしましょう
● 見やすいし、メンテもしやすい
RUN apt-get update && apt-get install -y
bzr
cvs
git
mercurial
subversion
38. 10. Leverage build cache
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● ビルドキャッシュを活用する
● レイヤはDockerfileの上の命令から作られる
● 2回目以降はキャッシュが使われて一瞬
● 変更があると、後続のレイヤ全てでキャッシュが破
棄される
○ よって変更されがちな処理は下の方で行う
39. 10. Leverage build cache - 2
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
ENTRYPOINT xxxx
VOLUME xxxx
EXPORT xxxx
ADD xxxx
RUN xxxx
COPY xxxx
RUN xxxx
FROM xxxx
変更が起きやすいコマンドは下の方にする
初回
ENTRYPOINT xxxx
VOLUME xxxx
EXPORT xxxx
ADD xxxx
RUN xxxx
COPY xxxx
RUN xxxx
FROM xxxx
2回目
ENTRYPOINT xxxx
VOLUME xxxx
EXPORT xxxx
ADD xxxx
RUN yyyy
COPY xxxx
RUN xxxx
FROM xxxx
RUNを変更した
40. 10. Leverage build cache - 3
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● ADD , COPYはファイルのハッシュをチェックして差
分が無ければキャッシュを利用する
● RUNではコマンドの文字列が同じならキャッシュを
利用する(apt updateもキャッシュ)
44. FROM
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● とにかく小さいイメージをベースとして使う
● 公式では”Alpine image”を推奨している(が時代は
変わってきたかも) https://speakerdeck.com/stormcat24/base-image-journey-2018
45. RUN
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 可能な限りコマンドはまとめる
○ 削除を別のレイヤでやるのは悪手
FROM ubuntu:14.04
RUN apt-get update &&
apt-get install -y curl nginx &&
rm -rf /var/lib/apt/lists/*
FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install -y curl nginx
RUN rm -rf /var/lib/apt/lists/*
46. RUN - 2
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 可能な限りコマンドはまとめる
○ 削除を別のレイヤでやるのは悪手
FROM ubuntu:14.04
RUN apt-get update &&
apt-get install -y curl nginx &&
rm -rf /var/lib/apt/lists/*
FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install -y curl nginx
RUN rm -rf /var/lib/apt/lists/*
47. CMD
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 基本的な用途はデフォルトコマンドの指定
● exec formを使い、shell formを(基本)使わない
CMD ["command","param1","param2"]
CMD command param1 param2
48. CMD - 2
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 基本的な用途はデフォルトコマンドの指定
● exec formを使い、shell formを(基本)使わない
CMD ["command","param1","param2"]
CMD command param1 param2
49. CMD - 3
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● exec formはそのままだと環境変数を展開できな
いため、使う場合は一度 shell -c に渡す
CMD ["shell","-c","echo $HOME"]
50. CMD - 4
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 毎回同じコマンドを使うのであれば、
ENTRYPOINTを使うべき
51. ADD or COPY
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● どちらも似たような機能だが、シンプルなCOPYをま
ずは推奨
● COPYはローカルのファイル/ディレクトリをイメージ
に追加する機能しか無い
52. ADD or COPY - 2
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● ADDはtarファイルを指定することで解凍しながら
ファイルを展開できる
○ gzip , bzip2 , xzに対応
ADD rootfs.tar.xz /.
解凍されて中のファイルが展
開される
53. ADD or COPY - 3
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● ADDはURLからファイル/ディレクトリを取得するこ
ともできる
ADD http://example.com/foobar /
54. ENTRYPOINT
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● イメージをコマンドのように扱うために使用
○ 以下の様にビルドした場合、
#Dockerfile
ENTRYPOINT ["s3cmd"]
CMD ["--help"]
$ docker build -t s3cmd .
55. ENTRYPOINT - 2
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● 単純にdocker runをすると “s3cmd --help”が実
行される(デフォルトのCMDが発動)
$ docker run s3cmd
-> ENTRYPOINTの “s3cmd” に CMDの “--help” が渡される
#Dockerfile
ENTRYPOINT ["s3cmd"]
CMD ["--help"]
56. ENTRYPOINT - 3
Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
● docker runで引数を渡して実行すると、CMDの指
定が上書きされて実行できる
$ docker run s3cmd ls s3://mybucket
-> ENTRYPOINTの “s3cmd” に 引数の “ls s3://mybucket” が渡される
*CMDは基本的にデフォルトのコマンドを記載する用途
#Dockerfile
ENTRYPOINT ["s3cmd"]
CMD ["--help"]