Docker2020

A97eee01397705443a72a48ce29d3e19?s=47 Cybozu
August 19, 2020

 Docker2020

A97eee01397705443a72a48ce29d3e19?s=128

Cybozu

August 19, 2020
Tweet

Transcript

  1. 開運研修 2020 Docker Neco 池添 明宏 1

  2. ⽬次 ▌はじめに ▌コンテナの仕組み ▌ハンズオン1: Dockerに触れてみる ▌Dockerベストプラクティス: Dockerfile編 ▌ハンズオン2: Dockerfileを書いてみる ▌Dockerベストプラクティス:

    アプリケーション編 ▌演習 2
  3. はじめに 3

  4. コンテナとDocker ▌コンテナとは l アプリケーションごとに隔離された環境を提供する仮想化 の仕組み ▌Dockerとは l 代表的なコンテナ実⾏ソフトウェア l コンテナランタイム、コンテナイメージの作成ツール、イ

    メージを共有する仕組みなども提供 4
  5. サイボウズでのコンテナ事情 ▌開発 l kintoneやGaroonチームでは開発環境としてDockerを利⽤ ▌テスト l CircleCIやJenkinsの実⾏環境としてDockerを利⽤ ▌運⽤ l YakumoとNecoでは、ほとんどのソフトウェアを

    Kubernetes上でコンテナとして動作させている 5
  6. サイボウズで開発しているコンテナ ▌レジストリ l https://quay.io/organization/ cybozu ▌NecoチームのDockerfile l https://github.com/cybozu/n eco-containers 6

  7. コンテナ利⽤のメリット ▌アプリケーションの動作環境を丸ごとパッケージング ▌開発・テスト・本番でソフトウェアの実⾏環境のギャップを⼩ さくすることができる ▌軽量であるため扱いやすくリソースの利⽤効率も⾼い 7

  8. コンテナの仕組み 8

  9. VMとコンテナの違い ▌VM: ・イメージサイズが⼤きい。 ・起動が遅い。 ・ホストと異なるOSの利⽤が可能。 ▌コンテナ: ・イメージサイズが⽐較的⼩さい。 ・起動が速い。 ・ホストとカーネルを共有。 Hardware

    Hypervisor VM VM OS プロセス プロセス OS プロセス プロセス ファイル ファイル Hardware Linux コンテナ コンテナ ファイル プロセス ファイル プロセス 9
  10. コンテナを実現するための技術要素 ▌Linux namespace l プロセスに対して、PID、ネットワーク、ユーザー、ホスト名な どのリソースを分離することができる。 ▌cgroups l CPUやメモリなどのリソースを制限・隔離することができる。 ▌Linux

    capability l 特権ポートへのアクセスやiptablesの操作などの権限を制御する ことができる。 10
  11. MacやWindows上のDockerは︖ ▌軽量なLinux VM上でDockerを動かして いる l Docker Desktop for Mac /

    Windows l Docker toolbox (legacy) ▌注意点 l Mac版はホストとコンテナ間で共有す るファイルのアクセスが遅い l コンテナ向けの実⾏ファイルはLinux ⽤にビルドする必要がある Docker Desktop for Mac のアーキテクチャ macOS Linux VM hyperkit macの プロセス Docker Container Runtime Docker CLI コンテナ コンテナ コンテナ 11
  12. Dockerの構成 Host Computer Container Image Dockerfile Docker コンテナランタイム コンテナ レジストリ

    コンテナ コンテナ コンテナ Container Image コンテナ イメージ docker build docker run docker push docker pull 12
  13. Dockerの構成要素 ▌Dockerfile l コンテナイメージの作成⼿順を記述したファイル ▌コンテナイメージ l コンテナの実⾏に必要なファイルなどをまとめたアーカイブファイル ▌コンテナ l 実際に実⾏されているコンテナ

    ▌Dockerコンテナランタイム l コンテナを実⾏するソフトウェア ▌コンテナレジストリ l コンテナイメージを共有するためのサービス (Docker Hubなど) 13
  14. コンテナオーケストレーションツール ▌複数のコンテナを組み合わせたアプリケーションを実⾏したり管理 するための仕組み ▌docker-compose l シングルホスト上で複数のコンテナを組み合わせて実⾏するた めのツール ▌Kubernetes l 複数のホスト上にコンテナを適切にスケジューリングしたり、

    コンテナの⾃動復旧やアップグレードなど様々な管理をおこ なってくれる。 14
  15. ハンズオン1 Dockerに触れてみる 15

  16. 準備: Dockerのセットアップ ▌Docker Desktop for Macを使いたい⼈ l 下記を参考にDockerをインストール l https://docs.docker.com/docker-for-mac/install/

    ▌Linux上でDockerを使いたい⼈ l 下記を参考にVirtualBoxとVagrantをインストール l https://www.virtualbox.org/wiki/Downloads l https://www.vagrantup.com/ 16
  17. 準備: ハンズオン向けサンプルの取得 17 # サンプルの取得 git clone https://github.com/zoetrope/training-docker.git # Vagrantを利⽤する場合

    vagrant up vagrant ssh
  18. ハンズオン1の内容 ▌コンテナイメージの取得 ▌コンテナの起動 ▌コンテナに⼊ってみる ▌ホストとのファイル共有 18

  19. よく使うDockerコマンド ▌ run : コンテナの実⾏ ▌ stop : コンテナの停⽌ ▌

    rm : コンテナの削除 ▌ ps : コンテナの確認 ▌ inspect : コンテナの詳細情報の取得 ▌ exec : コンテナ上でコマンドの実⾏ ▌ logs : コンテナのログを確認 ▌ build : コンテナイメージのビルド ▌ images : コンテナイメージの確認 ▌ rmi : コンテナイメージの削除 ▌ container prune : 停⽌コンテナの削除 ▌ image prune : 未使⽤イメージの削除 詳しくは docker <COMMAND> --help 19
  20. コンテナイメージの取得 20 # ローカルのコンテナイメージの表⽰ docker images # Docker Hubからコンテナイメージを取得する docker

    pull nginx:latest # 再度、ローカルのコンテナイメージの表⽰ docker images
  21. コンテナの起動 21 # コンテナの起動 # -d: バックグラウンドで起動 # --name: コンテナに名前をつける(省略した場合は⾃動で名前がつく)

    # -p 8080:80: コンテナの80番ポートをホストの8080番ポートにバインド docker run -d --name mynginx -p 8080:80 nginx:latest # 起動しているコンテナの確認 # コンテナの停⽌・削除 docker ps docker stop mynginx curl localhost:8080 docker rm mynginx docker logs mynginx
  22. コンテナに⼊ってみる 22 # ubuntu-debugコンテナ上でbashを実⾏する # -i: STDINをオープンし続ける -t: 擬似端末を割り当てる #

    --rm: コンテナ終了時にコンテナを⾃動削除 docker run -it --rm quay.io/cybozu/ubuntu-debug:18.04 /bin/bash # いろんなコマンドを叩いて、コンテナ内のプロセスやファイルシステム、 # ネットワークの状態などを確認してみる ls hostname ip a ps aux
  23. ホストとのファイル共有 23 # ホスト上で適当なHTMLファイルを作成 cd /path/to/html touch index.html # ホストの/path/to/htmlをコンテナの/usr/share/nginx/htmlにバインド

    docker run -d --name mynginx -p 8080:80 ¥ -v /path/to/html:/usr/share/nginx/html ¥ nginx:latest curl localhost:8080
  24. コンテナの後⽚付け ▌docker ps -a を実⾏してみよう ▌不要になったコンテナは docker rm コマンド または

    docker container prune コマンドで削除しよう ▌docker run の --rm オプションを活⽤しよう 24
  25. Dockerベストプラクティス Dockerfile編 25

  26. Dockerfileの書き⽅ 26 FROM quay.io/cybozu/ubuntu:18.04 # ベースとなるコンテナイメージの指定 # docker build時に実⾏される処理 COPY

    ./myapp /work/myapp # ホストからコンテナへのファイルコピー WORKDIR /work/myapp # ワークディレクトリの指定 RUN make && make install # 任意のコマンドの実⾏ # docker run時に実⾏されるコマンドや環境変数を指定 ENV PATH /usr/local/bin CMD [“myapp”, “--opt=hoge”]
  27. Dockerfileのベストプラクティス参考リンク ▌公式ドキュメント l https://docs.docker.com/develop/develop- images/dockerfile_best-practices ▌サイボウズ社内のドキュメント l http://wiki.dev.cybozu.co.jp/display/DEV/Docker%20G uide l

    https://github.com/cybozu-private/neco- wiki/blob/master/docs/dockerfile.md 27
  28. Dockerfileのベストプラクティス ▌野良コンテナイメージは使わない ▌コンテナイメージはできるだけ⼩さく ▌コマンドを正しく使う ▌タグを正しく使う ▌Lintツールを使う 28

  29. 野良コンテナイメージは使わない ▌脆弱性や悪意のあるコードが含まれているかも ▌Docker Official Images は⽐較的安全 ▌Necoチーム提供のベースコンテナイメージ推奨 ▌どれを使うにしてもよく調査すること 29

  30. コンテナイメージサイズはできるだけ⼩さく ▌⼤きなコンテナイメージ l ディスク容量を圧迫 l ダウンロードに時間がかかる ▌コンテナイメージを⼩さくする⽅法 l ⼩さなベースコンテナイメージを使う l

    レイヤーを意識する l multi-stage buildを使う 30
  31. ⼩さなコンテナイメージをベースにする イメージ名 サイズ 特徴 scratch 0B • からっぽのイメージ。libcもshellも⼊ってない。 • OS依存の脆弱性も含まないためセキュア。

    busybox 1.2MB • Linuxのユーティリティをシングルバイナリで提供。 • シングル実⾏バイナリのベースとして使われる。 Alpine Linux 5.6MB • 軽量なLinuxディストリビューション。 • ハマりどころが多い。(Necoでは利⽤禁⽌) distroless 16.9MB 〜 • 各種⾔語⽤の実⾏に必要なランタイムだけを持つ。 • Java, Python, Node.js⽤など⾔語ごとのイメージ。 cybozu/ubuntu 103MB • Necoチームが管理しているベースイメージ。 • 適切な脆弱性対応を実施している。 31
  32. レイヤーを意識する ▌RUNやCOPYを実⾏するたびに、 read-onlyなレイヤーが積み重 なっていく。 ▌中間ファイルをレイヤーに含め てしまうと、あとのレイヤーで 削除してもコンテナイメージの サイズは⼩さくならない。 FROM quay.io/cybozu/ubuntu:18.04

    RUN apt-get update RUN apt-get install build-essential COPY ./work/myapp /work RUN make RUN rm –rf ./tmp/ 32
  33. レイヤーをできるだけ少なくする FROM ubuntu:18.04 RUN apt-get update RUN apt-get install -y

    ¥ curl automake ¥ build-essential RUN rm –rf /var/lib/apt-lists/* ◦良い例 FROM ubuntu:18.04 RUN apt-get update && ¥ apt-get install -y ¥ curl automake ¥ build-essential && ¥ rm –rf /var/lib/apt-lists/* ✖悪い例 33
  34. キャッシュを意識してレイヤーを分割する ▌docker buildの際、変更の必要のないレイヤーはキャッシュ が利⽤される。 ▌キャッシュを意識してレイヤーを分割することで、docker buildの時間を短縮することが可能になる。 ▌ADDやCOPYコマンドでは、ファイルのチェックサムを利⽤ して変更を検知している。 34

  35. キャッシュを意識してレイヤーを分割する例 FROM ubuntu:18.04 COPY myapp ./ RUN apt-get update &&¥

    apt-get install -y ¥ build-essential && ¥ rm –rf /var/lib/apt-lists/* && ¥ make ◦良い例 FROM ubuntu:18.04 RUN apt-get update &&¥ apt-get install -y ¥ build-essential && ¥ rm –rf /var/lib/apt-lists/* COPY myapp ./ RUN make ✖悪い例 35
  36. multi-stage build ▌ひとつのDockerfileを複数のステージに分けて記述できる ▌利⽤例 l ビルド⽤と実⾏⽤のステージを分離 l ビルド⽤コンテナで実⾏ファイルをビルド l 実⾏ファイルを実⾏⽤コンテナにコピーしてイメージとし

    て保存 ▌ビルドに必要なツールや中間ファイルが実⾏⽤コンテナに含ま れないため、イメージサイズを⼩さくできる︕ 36
  37. multi-stage buildの例 37 # Stage1: ビルド⽤コンテナ FROM quay.io/cybozu/golang:1.12-bionic AS build

    COPY ./src /work/src WORKDIR /work/src RUN go install ./... # 実⾏ファイルのビルド # Stage2: 実⾏⽤コンテナ FROM quay.io/cybozu/ubuntu:18.04 COPY --from=build /go/bin / # 実⾏ファイルを Stage1 からコピーする ENTRYPOINT [“/myapp”]
  38. コマンドを正しく使う ▌ADDとCOPY l ADDは予期せぬ動きをする場合がある。通常はCOPYを使 えば⼗分。 ▌ENTRYPOINTとCMD l コンテナ起動時に実⾏するコマンドが限定されている場合 はENTRYPOINTを使う。 l

    ⾊々なコマンドを実⾏して使うコンテナはCMDを使う。 38
  39. タグを正しく使う ▌Dockerイメージのタグは、容易に更新できてしまう。 l 同⼀のタグを使っているつもりが、異なるコンテナイメー ジを使っていた、なんてことも… ▌Necoチームでのタグ運⽤ルール l レジストリにあげるイメージは必ず固定タグをつける。固 定タグは変更しない。 l

    利便性のためにブランチタグも利⽤可能。 l latestタグは利⽤しない。 39
  40. Lintツールを使う ▌hadolint l https://github.com/hadolint/hadolint l Dockerfileの静的解析ツール l Yakumoチームでも利⽤ 40

  41. ハンズオン2 Dockerfileを書いてみる 41

  42. ハンズオン2の内容 ▌docker buildしてみる ▌multi-stage buildを使ってみる ▌hadolintでチェックしてみる 42

  43. コンテナイメージのビルド⽅法 ▌Dockerfileのあるディレクトリに移動してdocker buildを実⾏ l -t オプションでコンテナイメージの名前とタグを指定 l タグを省略すると latest になる

    l 最後の . は Dockerfile の場所を指定している cd training-docker/02_dockerfile/helloworld docker build –t helloworld:v1 . 43
  44. Dockerfileのサンプル ▌training-docker/02_dockerfile/helloworld l ubuntuにnode.jsをインストールして、簡単なHTTPサーバ を起動するコンテナ ▌training-docker/02_dockerfile/multi_stage l multi-stage buildのサンプル l

    stage 1: Goの開発環境でプログラムをビルド l stage 2: 空のイメージに実⾏ファイルだけをコピー 44
  45. コンテナイメージをビルドして動かしてみる 45 # Dockerfileのあるディレクトリに移動してビルド docker build -t helloworld:v1 . #

    Lintツールでチェックしてみる docker run --rm -i hadolint/hadolint /bin/hadolint - < Dockerfile # 確認 docker images docker history helloworld:v1 # 起動してみる docker run --r -d --name helloworld -p 3000:3000 helloworld:v1 curl localhost:3000
  46. コンテナイメージの後⽚付け ▌docker images を実⾏してみよう ▌不要になったイメージは docker rmi コマンド または docker

    image prune コマンドで削除しよう 46
  47. Dockerベストプラクティス アプリケーション編 47

  48. コンテナアプリケーションのベストプラクティス ▌コンテナはステートレスにする ▌ひとつのコンテナにはひとつの役割 ▌正しくログを出す ▌シグナルを処理する ▌ヘルスチェックの仕組みを⽤意する ▌柔軟なアプリケーション設定 48

  49. コンテナはステートレスにする ▌コンテナ内でアプリケーションを更新したり、ファイルを保存 したりしない。 ▌なぜ︖ l コンテナが状態を保持すると、いつでもどこでも同じ構成 であることが保証できなくなる。 l 状態を保持していなければ、コンテナをいつでも再起動し たり更新したりできる。

    49
  50. ステートレスにするには ▌コンテナイメージを更新するには、コンテナの中でコマンドを 実⾏するのではなく、Dockerfileを変更する ▌データを永続化したい場合は、Docker や Kubernetes の Volume機能を利⽤する ▌docker run

    に --read-only オプションを指定 50
  51. Volumeとは ▌Volumeはコンテナが利⽤するデータを永続 化するための仕組み。 ▌コンテナとライフサイクルが異なるため、コ ンテナを終了してもVolumeは消えない。 ▌複数のコンテナ間でVolumeを共有すること も可能。 51 コンテナ Volume

    マウント
  52. Volumeの使い⽅ 52 # volumeを作成する docker volume create vol1 docker volume

    ls # volumeをマウントしてコンテナを起動 docker run -it --name ubuntu -v vol1:/mnt/data quay.io/cybozu/ubutun:18.04 bash > touch /mnt/data/hoge.txt # コンテナを削除、もう⼀度コンテナを⽴ち上げ直してファイルの存在を確認 docker rm ubuntu docker run -it --name ubuntu -v vol1:/mnt/data quay.io/cybozu/ubutun:18.04 bash > ls /mnt/data
  53. ひとつのコンテナにはひとつの役割 ▌コンテナは役割ごとに分割する。 ▌なぜ︖ l コンテナイメージが再利⽤しやすく なる l スケールさせやすくなる l メンテナンスしやすくなる

    コンテナ App サーバ 全⽂検索 エンジン データ ベース わるい例 コンテナ App サーバ コンテナ 全⽂検索 エンジン コンテナ データ ベース よい例 53
  54. docker-compose ▌docker-composeを利⽤すると、複数のコンテナの起動を管理 できる。 ▌構成ファイルをdocker-compose.ymlに記述する l 03_application/compose参照 ▌起動・停⽌ l docker-compose up

    l docker-compose down 54
  55. docker-compose.ymlの記述例 55 version: '3' # 起動するコンテナの設定を記述 services: # データベース⽤コンテナの設定 etcd:

    container_name: etcd image: quay.io/cybozu/etcd:3.3 ports: - 2379 volumes: - etcd-data:/var/lib/etcd # アプリケーション⽤コンテナの設定 todo: container_name: todo image: todo:v1 ports: - 9000:9000 # 利⽤するVolumeの⼀覧を記述 volumes: etcd-data:
  56. 正しくログを出そう ▌ファイルではなく、標準出⼒ or 標準エラー出⼒にログを出す。 ▌ログのローテーションや転送は、DockerやKubernetesが⽤意 しているログの仕組みに任せる。 56

  57. シグナルを処理しよう ▌docker stop を実⾏するとコンテナに SIGTERM シグナルが⾶ んでくる。 ▌シグナルを受け取ったらアプリケーションを正しく終了させる。 l Graceful

    Shutdown 機能として、ライブラリやWebサー バーが提供していることもある。 l Node.js などではシグナルの扱いに注意 (参考: PID 1問題) 57
  58. ヘルスチェックの仕組みを⽤意する ▌コンテナが正しく動作しているかどうか確認するための⼿段を ⽤意しておこう。 ▌ヘルスチェック⽤のWeb APIを⽤意するのが⼀般的。 ▌DockerのHEALTCHECK機能や、Kubernetesのliveness probe機能を利⽤して、コンテナの死活監視がおこなえる。 58

  59. エラーが起きたら終了させよう ▌アプリケーションが⾃⼒では解決できないエラーが発⽣した場 合は、プロセスをエラー終了させる。 l 例: データベース接続エラー、設定ファイル記述ミスなど ▌エラーの検出・復旧やアラート通知は外部のシステムに任せる 59

  60. 柔軟なアプリケーション設定 ▌アプリケーションの設定は外部から変更可能にする。 l 環境変数 l コマンドラインオプション l 設定ファイル 60

  61. コンテナアプリケーションを安全に動かす ▌最新のDockerを利⽤する ▌ベースイメージを適切に更新 ▌docker.socketファイルの扱いに注意 ▌rootユーザーやprivileged権限で実⾏しない ▌ホストへのアクセスは最⼩限に ▌秘密情報をコンテナイメージに含めない ▌コンテナイメージの脆弱性チェックを実施 61

  62. コンテナアプリケーションのサンプル ▌training-docker/03_application/bestpractice l アプリケーションログとアクセスログをSTDERRに出す l SIGTERMを受けるとGraceful Shutdownする l ヘルスチェック⽤のAPIを持つ l

    ポート番号を環境変数で設定可能 62
  63. 演習 63

  64. 演習課題 ▌任意のアプリケーションをDockerで動かしてみてください l 例: 開運研修「Webアプリケーション基礎」で作成した Webアプリなど。 l コンテナのベースイメージは quay.io/cybozu/ubuntu:18.04 を利⽤してください。

    l 本研修で紹介したプラクティスを取り⼊れてみてください。 64
  65. 参考情報 ▌ Docker: Up & Running, 2nd Edition ▌ 分散システムデザインパターン

    ▌ Software Design 2019年6⽉号 「IT業界ビギナーのためのDocker+k8s⼊⾨講座」 ▌ Dockerfileを改善するためのBest Practice 2019年版 ▌ Dockerfileを書くためのベストプラクティス解説編 ▌ Base Image Journey 2018 ▌ Best practices for building containers ▌ Best Practices for Operating Containers ▌ The Twelve-Factor App ▌ コンテナ技術⼊⾨ - 仮想化との違いを知り、要素技術を触って学ぼう 65