Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

はじめに 3

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

サイボウズでのコンテナ事情 ▌開発 l kintoneやGaroonチームでは開発環境としてDockerを利⽤ ▌テスト l CircleCIやJenkinsの実⾏環境としてDockerを利⽤ ▌運⽤ l YakumoとNecoでは、ほとんどのソフトウェアを Kubernetes上でコンテナとして動作させている 5

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

コンテナの仕組み 8

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

コンテナを実現するための技術要素 ▌Linux namespace l プロセスに対して、PID、ネットワーク、ユーザー、ホスト名な どのリソースを分離することができる。 ▌cgroups l CPUやメモリなどのリソースを制限・隔離することができる。 ▌Linux capability l 特権ポートへのアクセスやiptablesの操作などの権限を制御する ことができる。 10

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Dockerの構成 Host Computer Container Image Dockerfile Docker コンテナランタイム コンテナ レジストリ コンテナ コンテナ コンテナ Container Image コンテナ イメージ docker build docker run docker push docker pull 12

Slide 13

Slide 13 text

Dockerの構成要素 ▌Dockerfile l コンテナイメージの作成⼿順を記述したファイル ▌コンテナイメージ l コンテナの実⾏に必要なファイルなどをまとめたアーカイブファイル ▌コンテナ l 実際に実⾏されているコンテナ ▌Dockerコンテナランタイム l コンテナを実⾏するソフトウェア ▌コンテナレジストリ l コンテナイメージを共有するためのサービス (Docker Hubなど) 13

Slide 14

Slide 14 text

コンテナオーケストレーションツール ▌複数のコンテナを組み合わせたアプリケーションを実⾏したり管理 するための仕組み ▌docker-compose l シングルホスト上で複数のコンテナを組み合わせて実⾏するた めのツール ▌Kubernetes l 複数のホスト上にコンテナを適切にスケジューリングしたり、 コンテナの⾃動復旧やアップグレードなど様々な管理をおこ なってくれる。 14

Slide 15

Slide 15 text

ハンズオン1 Dockerに触れてみる 15

Slide 16

Slide 16 text

準備: 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

Slide 17

Slide 17 text

準備: ハンズオン向けサンプルの取得 17 # サンプルの取得 git clone https://github.com/zoetrope/training-docker.git # Vagrantを利⽤する場合 vagrant up vagrant ssh

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

よく使うDockerコマンド ▌ run : コンテナの実⾏ ▌ stop : コンテナの停⽌ ▌ rm : コンテナの削除 ▌ ps : コンテナの確認 ▌ inspect : コンテナの詳細情報の取得 ▌ exec : コンテナ上でコマンドの実⾏ ▌ logs : コンテナのログを確認 ▌ build : コンテナイメージのビルド ▌ images : コンテナイメージの確認 ▌ rmi : コンテナイメージの削除 ▌ container prune : 停⽌コンテナの削除 ▌ image prune : 未使⽤イメージの削除 詳しくは docker --help 19

Slide 20

Slide 20 text

コンテナイメージの取得 20 # ローカルのコンテナイメージの表⽰ docker images # Docker Hubからコンテナイメージを取得する docker pull nginx:latest # 再度、ローカルのコンテナイメージの表⽰ docker images

Slide 21

Slide 21 text

コンテナの起動 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

Slide 22

Slide 22 text

コンテナに⼊ってみる 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

Slide 23

Slide 23 text

ホストとのファイル共有 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

Slide 24

Slide 24 text

コンテナの後⽚付け ▌docker ps -a を実⾏してみよう ▌不要になったコンテナは docker rm コマンド または docker container prune コマンドで削除しよう ▌docker run の --rm オプションを活⽤しよう 24

Slide 25

Slide 25 text

Dockerベストプラクティス Dockerfile編 25

Slide 26

Slide 26 text

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”]

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

Dockerfileのベストプラクティス ▌野良コンテナイメージは使わない ▌コンテナイメージはできるだけ⼩さく ▌コマンドを正しく使う ▌タグを正しく使う ▌Lintツールを使う 28

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

⼩さなコンテナイメージをベースにする イメージ名 サイズ 特徴 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

Slide 32

Slide 32 text

レイヤーを意識する ▌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

Slide 33

Slide 33 text

レイヤーをできるだけ少なくする 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

Slide 34

Slide 34 text

キャッシュを意識してレイヤーを分割する ▌docker buildの際、変更の必要のないレイヤーはキャッシュ が利⽤される。 ▌キャッシュを意識してレイヤーを分割することで、docker buildの時間を短縮することが可能になる。 ▌ADDやCOPYコマンドでは、ファイルのチェックサムを利⽤ して変更を検知している。 34

Slide 35

Slide 35 text

キャッシュを意識してレイヤーを分割する例 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

Slide 36

Slide 36 text

multi-stage build ▌ひとつのDockerfileを複数のステージに分けて記述できる ▌利⽤例 l ビルド⽤と実⾏⽤のステージを分離 l ビルド⽤コンテナで実⾏ファイルをビルド l 実⾏ファイルを実⾏⽤コンテナにコピーしてイメージとし て保存 ▌ビルドに必要なツールや中間ファイルが実⾏⽤コンテナに含ま れないため、イメージサイズを⼩さくできる︕ 36

Slide 37

Slide 37 text

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”]

Slide 38

Slide 38 text

コマンドを正しく使う ▌ADDとCOPY l ADDは予期せぬ動きをする場合がある。通常はCOPYを使 えば⼗分。 ▌ENTRYPOINTとCMD l コンテナ起動時に実⾏するコマンドが限定されている場合 はENTRYPOINTを使う。 l ⾊々なコマンドを実⾏して使うコンテナはCMDを使う。 38

Slide 39

Slide 39 text

タグを正しく使う ▌Dockerイメージのタグは、容易に更新できてしまう。 l 同⼀のタグを使っているつもりが、異なるコンテナイメー ジを使っていた、なんてことも… ▌Necoチームでのタグ運⽤ルール l レジストリにあげるイメージは必ず固定タグをつける。固 定タグは変更しない。 l 利便性のためにブランチタグも利⽤可能。 l latestタグは利⽤しない。 39

Slide 40

Slide 40 text

Lintツールを使う ▌hadolint l https://github.com/hadolint/hadolint l Dockerfileの静的解析ツール l Yakumoチームでも利⽤ 40

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

コンテナイメージのビルド⽅法 ▌Dockerfileのあるディレクトリに移動してdocker buildを実⾏ l -t オプションでコンテナイメージの名前とタグを指定 l タグを省略すると latest になる l 最後の . は Dockerfile の場所を指定している cd training-docker/02_dockerfile/helloworld docker build –t helloworld:v1 . 43

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

コンテナイメージをビルドして動かしてみる 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

Slide 46

Slide 46 text

コンテナイメージの後⽚付け ▌docker images を実⾏してみよう ▌不要になったイメージは docker rmi コマンド または docker image prune コマンドで削除しよう 46

Slide 47

Slide 47 text

Dockerベストプラクティス アプリケーション編 47

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

Volumeとは ▌Volumeはコンテナが利⽤するデータを永続 化するための仕組み。 ▌コンテナとライフサイクルが異なるため、コ ンテナを終了してもVolumeは消えない。 ▌複数のコンテナ間でVolumeを共有すること も可能。 51 コンテナ Volume マウント

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

ひとつのコンテナにはひとつの役割 ▌コンテナは役割ごとに分割する。 ▌なぜ︖ l コンテナイメージが再利⽤しやすく なる l スケールさせやすくなる l メンテナンスしやすくなる コンテナ App サーバ 全⽂検索 エンジン データ ベース わるい例 コンテナ App サーバ コンテナ 全⽂検索 エンジン コンテナ データ ベース よい例 53

Slide 54

Slide 54 text

docker-compose ▌docker-composeを利⽤すると、複数のコンテナの起動を管理 できる。 ▌構成ファイルをdocker-compose.ymlに記述する l 03_application/compose参照 ▌起動・停⽌ l docker-compose up l docker-compose down 54

Slide 55

Slide 55 text

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:

Slide 56

Slide 56 text

正しくログを出そう ▌ファイルではなく、標準出⼒ or 標準エラー出⼒にログを出す。 ▌ログのローテーションや転送は、DockerやKubernetesが⽤意 しているログの仕組みに任せる。 56

Slide 57

Slide 57 text

シグナルを処理しよう ▌docker stop を実⾏するとコンテナに SIGTERM シグナルが⾶ んでくる。 ▌シグナルを受け取ったらアプリケーションを正しく終了させる。 l Graceful Shutdown 機能として、ライブラリやWebサー バーが提供していることもある。 l Node.js などではシグナルの扱いに注意 (参考: PID 1問題) 57

Slide 58

Slide 58 text

ヘルスチェックの仕組みを⽤意する ▌コンテナが正しく動作しているかどうか確認するための⼿段を ⽤意しておこう。 ▌ヘルスチェック⽤のWeb APIを⽤意するのが⼀般的。 ▌DockerのHEALTCHECK機能や、Kubernetesのliveness probe機能を利⽤して、コンテナの死活監視がおこなえる。 58

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

コンテナアプリケーションのサンプル ▌training-docker/03_application/bestpractice l アプリケーションログとアクセスログをSTDERRに出す l SIGTERMを受けるとGraceful Shutdownする l ヘルスチェック⽤のAPIを持つ l ポート番号を環境変数で設定可能 62

Slide 63

Slide 63 text

演習 63

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

参考情報 ▌ 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