Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

Introduce that Best practices for writing Dockerfiles

3 101 vues

Publié le

Japan Container Days V18.12でお話させて頂いた、「改めてDockerfileのベストプラクティスを振り返ろう」の資料になります。

Publié dans : Technologie
  • Soyez le premier à commenter

Introduce that Best practices for writing Dockerfiles

  1. 1. 改めてDockerfileの ベストプラクティス を振り返ろう オイシックス・ラ・大地(株) 林 如弥 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w JapanContainerDays v18.12 2018-12-05
  2. 2. 本日の流れ ● 今日のゴール ● Dockerfileの基礎 ● ベストプラクティスを振り返る ● まとめ Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
  3. 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
  4. 4. 今日のゴール
  5. 5. 今日のゴール ● 良いDockerfile書けそう、という気分を得る ● Dockerfileベストプラクティスの存在を知る ● 少なくともMulti Stage buildだけは覚える Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w
  6. 6. Dockerfileの基礎
  7. 7. Dockerfileとは? - 1 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● Dockerのイメージを自動で作成するための 命令書 ● テキストファイル ● “docker build”コマンドで実行する
  8. 8. Dockerfileとは? - 2 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w FROM debian:stable RUN apt-get update && apt-get install -y --force-yes apache2 EXPOSE 80 443 VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"] ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] 例) apacheのDockerfile
  9. 9. Dockerfileとは? - 3 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w 全部で18個の命令語を駆使する(と言っても良く使う 命令語は限られるけど) FROM RUN CMD LABEL MAINTAINER EXPORT ENV ADD COPY ENTRYPOINT VOLUME USER WORKDIR ARGS ONBUILD STOPSIGNAL HEALTHCHECK SHELL
  10. 10. Dockerfileとは? - 3 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w MAINTAINERはDeprecatedなので今後は使わ ないようにしましょう。よって実質17個 FROM RUN CMD LABEL MAINTAINER EXPORT ENV ADD COPY ENTRYPOINT VOLUME USER WORKDIR ARGS ONBUILD STOPSIGNAL HEALTHCHECK SHELL
  11. 11. ベストプラクティスを振り返る
  12. 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. 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. 14. Dockerfileのベストプラクティスとは? Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● 以下の4章で構成(雑な日本語訳) ○ 一般的なガイドラインと、使い方推奨 ○ 各命令語についての使い方推奨 ○ オフィシャルなサンプル集 ○ 追加情報へのリンク集
  15. 15. Dockerfileのベストプラクティスとは? Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● 以下の4章で構成(雑な日本語訳) ○ 一般的なガイドラインと、使い方推奨 ○ 各命令語についての使い方推奨 ○ オフィシャルなサンプル集 ○ 追加情報へのリンク集 内容の90%はこの2章分
  16. 16. Dockerfileのベストプラクティスとは? Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● 以下の4章で構成(雑な日本語訳) ○ 一般的なガイドラインと、使い方推奨 ○ 各命令語についての使い方推奨 ○ オフィシャルなサンプル集 ○ 追加情報へのリンク集 本セッションではこの2章から、 個人的に良かった物を抜粋して お話します
  17. 17. Dockerfileのベストプラクティス (General guidelines and recommendations)
  18. 18. General guidelines and recommendations は以下の10節より構成 1. Create ephemeral containers 2. Understand build context 3. Pipe Dockerfile through stdin 4. Exclude with .dockerignore 5. Use multi-stage builds 6. Don’t install unnecessary packages 7. Decouple applications 8. Minimize the number of layers 9. Sort multi-line arguments 10. Leverage build cache
  19. 19. 1. Create ephemeral containers Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● ステートレスなコンテナを作るべし ○ 停止=データは削除される ○ バージョンアップも削除→新規作成 ○ The Twelve Factor Appに従う ○ 軽量で小さな単位でコンテナ化する
  20. 20. 2. Understand build context Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● docker build時にどこでビルドされるのかを理解す る ○ ビルドする場所=ビルドコンテクスト ○ デフォルトはカレントディレクトリ ○ -f でビルドする場所を指定できる ○ -f でDockerfileとビルドコンテクストを分けるこ とも
  21. 21. 2. Understand build context - 2 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● デフォルトはカレントディレクトリ docker build -t hogeapp:v0.1 . ├── Dockerfile ├── data │ ├── data1 │ └── data2 └── hoge.config
  22. 22. 2. Understand build context - 3 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● -f でビルドする場所を指定できる docker build -t hogeapp:v0.1 -f context └── context ├── Dockerfile ├── data │ ├── data1 │ └── data2 └── hoge.config “context”というディレクトリに全 部入れた
  23. 23. 2. Understand build context - 4 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● Dockerfileとコンテクストを分けることも docker build -t hogeapp:v0.1 -f dockerfile-dir/Dockerfile context ├── context │ ├── data │ │ ├── data1 │ │ └── data2 │ └── hoge.config └── dockerfile-dir └── Dockerfile “context”というディレクトリにはイ メージで使うファイルなど “dockerfile-dir”というディレクトリ にはDockerfileを
  24. 24. 3. Pipe Dockerfile through stdin Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● Dockerfileを作成しなくても、パイプラインで標準 出力からdocker buildへコマンドを渡せる ● さらにリモートのビルドコンテクストにも標準出力か らDockerfileを渡せる
  25. 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. 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. 27. 4. Exclude with .dockerignore Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● 余計なファイルをイメージに入れないため に.dockerignoreファイルを使用する ● .gitignoreのDockerfile版(書式も同じ) */temp* */*/temp* temp?
  28. 28. 5. Use multi-stage builds Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● Dockerfile革命的な機能であるマルチステージビ ルドを使う ● Go言語のような、Go言語としてのビルドに必要な ファイル群と、実行に必要なGoバイナリがきっちり 分離できるような用途に最適
  29. 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. 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. 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. 32. 6. Don’t install unnecessary packages Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● 不必要なパッケージは入れない ● net-toolsとかvimとか”あると便利”なだけで、必須 でなければ入れない (入れたい気持ちはわかるけど)
  33. 33. 7. Decouple applications Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● 1コンテナ=1アプリケーションが原則 ● DB、キャッシュ、WEBはちゃんと別コンテナに分け ること ● ただし1コンテナあたり1プロセスに制限してしまう と、apacheのようなセッション単位でプロセス増や すソフトウェアもあるから注意
  34. 34. 8. Minimize the number of layers Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● レイヤ数は可能な限り減らす ● RUN, COPY, ADDだけがレイヤを増やすので、こ れらの命令語を使用するときに意識する ○ LABEL等もレイヤ作るけどサイズに影響はしな い ● マルチステージビルド使ってね
  35. 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. 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. 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. 38. 10. Leverage build cache Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● ビルドキャッシュを活用する ● レイヤはDockerfileの上の命令から作られる ● 2回目以降はキャッシュが使われて一瞬 ● 変更があると、後続のレイヤ全てでキャッシュが破 棄される ○ よって変更されがちな処理は下の方で行う
  39. 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. 40. 10. Leverage build cache - 3 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● ADD , COPYはファイルのハッシュをチェックして差 分が無ければキャッシュを利用する ● RUNではコマンドの文字列が同じならキャッシュを 利用する(apt updateもキャッシュ)
  41. 41. Dockerfileのベストプラクティス (Dockerfile instructions)
  42. 42. Dockerfile instructions は以下の12節より構成 1. FROM 2. LABEL 3. RUN 4. CMD 5. EXPOSE 6. ENV 7. ADD or COPY 8. ENTRYPOINT 9. VOLUME 10. USER 11. WORKDIR 12. ONBUILD
  43. 43. Dockerfile instructions は以下の12節より構成 1. FROM 2. LABEL 3. RUN 4. CMD 5. EXPOSE 6. ENV 7. ADD or COPY 8. ENTRYPOINT 9. VOLUME 10. USER 11. WORKDIR 12. ONBUILD
  44. 44. FROM Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● とにかく小さいイメージをベースとして使う ● 公式では”Alpine image”を推奨している(が時代は 変わってきたかも) https://speakerdeck.com/stormcat24/base-image-journey-2018
  45. 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. 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. 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. 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. 49. CMD - 3 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● exec formはそのままだと環境変数を展開できな いため、使う場合は一度 shell -c に渡す CMD ["shell","-c","echo $HOME"]
  50. 50. CMD - 4 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● 毎回同じコマンドを使うのであれば、 ENTRYPOINTを使うべき
  51. 51. ADD or COPY Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● どちらも似たような機能だが、シンプルなCOPYをま ずは推奨 ● COPYはローカルのファイル/ディレクトリをイメージ に追加する機能しか無い
  52. 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. 53. ADD or COPY - 3 Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● ADDはURLからファイル/ディレクトリを取得するこ ともできる ADD http://example.com/foobar /
  54. 54. ENTRYPOINT Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● イメージをコマンドのように扱うために使用 ○ 以下の様にビルドした場合、 #Dockerfile ENTRYPOINT ["s3cmd"] CMD ["--help"] $ docker build -t s3cmd .
  55. 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. 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"]
  57. 57. まとめ (というか振り返って読んだ感想)
  58. 58. まとめ(感想) Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ● ADDとCOPY、CMDとENTRYPOINTの使いわけ が初見で難しいが、覚える必要がある ● マルチステージビルドは成果物だけを見るなら非 常に効果的(ビルド時間とか言い出すと...) ● 使えるものもあれば、微妙な物も....
  59. 59. 今日のゴール(再掲) ● 良いDockerfile書けそう、という気分を得る ● Dockerfileベストプラクティスの存在を知る ● 少なくともMulti Stage buildだけは覚える Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w ご静聴感謝! m(_ _)m
  60. 60. おすすめなイベント紹介 コンテナのビルドの変人 達人の集い Container Builders Meetup https://build.connpass.com/ Photo by Alexandr Podvalny on Unsplash: https://unsplash.com/photos/WOxddhzhC1w 始終圧倒されっぱなしの Meetupでした!!!

×