Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2019-10 Docker

2019-10 Docker

A97eee01397705443a72a48ce29d3e19?s=128

Cybozu
PRO

June 24, 2019
Tweet

More Decks by Cybozu

Other Decks in Technology

Transcript

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

  2. 目次 ▌はじめに ▌コンテナの仕組み ▌Dockerベストプラクティス ⚫ Dockerfile編 ⚫ アプリケーション編 ▌演習 2

  3. はじめに 3

  4. コンテナとDocker ▌コンテナとは ⚫ アプリケーションごとに隔離された環境を提供する仮想化 の仕組み ▌Dockerとは ⚫ もっとも代表的なコンテナ実行ソフトウェア ⚫ コンテナを実行するソフトウェアだけでなく、コンテナイ

    メージの作成やイメージを共有する仕組みなどのエコシス テムも提供する 4
  5. サイボウズでのコンテナ事情 ▌開発 ⚫ いくつかの開発チームでは開発環境としてDockerを利用 ▌テスト ⚫ CircleCIやJenkinsの実行環境としてDockerを利用 → 詳しくは開運研修「CI/CD」で ▌運用

    ⚫ YakumoやNecoでは、ほとんどのソフトウェアをKubernetes 上でコンテナとして動作させている → 詳しくは開運研修「Kubernetesを使った開発入門」で 5
  6. Necoで開発しているコンテナ ▌レジストリ ⚫ https://quay.io/organization/ cybozu ▌Dockerfile ⚫ https://github.com/cybozu/u buntu-base/ ⚫

    https://github.com/cybozu/n eco-containers 6
  7. コンテナ利用のメリット ▌Batteries included, but removable ▌Build once, Run anywhere ▌アプリケーションの動作環境を丸ごとパッケージにまとめて、ひと

    つのファイルとして扱うことができる。 ▌開発・テスト・本番でソフトウェアの実行環境のギャップを小さく することができる。「手元で動いたのに!?」が減らせる。 ▌VMと比較して軽量であるため扱いやすく、リソースの利用効率も 高くなる。 7
  8. コンテナの仕組み 8

  9. VMとコンテナの違い Hardware Hypervisor VM VM OS プロセス プロセス OS プロセス

    プロセス Hardware Linux コンテナ コンテナ ファイル プロセス ファイル プロセス VM: ・仮想的なサーバを用意し、その上にOSを セットアップ。 ・イメージサイズが大きい。 ・起動が遅い(OSの起動時間)。 ・ホストと異なるOSを動かすことができる。 コンテナ: ・Linuxカーネルの機能を利用してプロセス を隔離。 ・イメージサイズが比較的小さい。 ・起動が速い(通常のプロセスと同等)。 ・ホストとカーネルを共有。 ファイル ファイル 9
  10. コンテナを実現するための技術要素 ▌Linux namespace ⚫ プロセスに対して、PID空間、ネットワーク空間、ユーザー空間、 ホスト名などのリソースを分離することができる。 ▌cgroups ⚫ CPUやメモリなどのリソースを制限・隔離することができる。 ⚫

    開運研修「LinuxサーバのCPUやメモリリソースの管理につい て」で詳しく解説。 ▌Linux capability ⚫ 特権ポートへのアクセスやiptablesへのアクセス権などの権限を 制御することができる。 10
  11. Host Computer Dockerの構成 Container Image Dockerfile Docker Container Runtime Container

    Registry Container Container Container Container Image Container Image docker build docker run docker push docker pull 11
  12. Dockerの構成要素 ▌ Dockerfile ⚫ Container Imageの作成手順を記述したファイル ▌ Container Image ⚫

    コンテナの実行に必要なファイルなどをまとめたアーカイブファイル ▌ Container ⚫ 実際に実行されているコンテナ ▌ Docker Container Runtime ⚫ コンテナを実行するソフトウェア ▌ Container Registry ⚫ Container Imageを共有するためのサービス ⚫ Docker Hub, Quay.io, GCR(Google Container Registry)など 12
  13. MacやWindows上のDockerは? ▌軽量なLinux VM上でDockerを動かしている ⚫ Docker Desktop for Mac / Windows

    ⚫ Docker toolbox (legacy) ▌注意点 ⚫ Mac版はホストとコンテナ間で共有する ファイルのアクセスが遅い ⚫ Docker DesktopはWindows Home Editionで動かない (WSL2対応で改善) ⚫ コンテナ向けの実行ファイルはLinux用に ビルドする必要がある macOS Linux VM hyperkit macの プロセス Docker Container Runtime Docker CLI コンテナ コンテナ コンテナ Docker Desktop for Mac のアーキテクチャ 13
  14. コンテナオーケストレーションツール ▌複数のコンテナを組み合わせたアプリケーションを実行したり管理 するための仕組み ▌docker-compose ⚫ シングルホスト上で複数のコンテナを組み合わせて実行するた めのツール ▌Kubernetes ⚫ 複数のホスト上にコンテナを適切にスケジューリングしたり、

    コンテナの自動復旧やアップグレードなど様々な管理をおこ なってくれる。 ⚫ デファクトスタンダード 14
  15. ハンズオン1 Dockerに触れてみる 15

  16. 準備 ▌Dockerのセットアップ ⚫ Docker Desktop for Macを使いたい人 ⚫ https://docs.docker.com/docker-for-mac/install/ ⚫

    VMを立ててやってみたい人 ⚫ https://www.virtualbox.org/wiki/Downloads ⚫ https://www.vagrantup.com/ ▌サンプルファイルの取得 ⚫ git clone https://github.com/zoetrope/training- docker.git 16
  17. ハンズオンの内容 ▌コンテナイメージの取得 ▌コンテナの起動 ▌コンテナに入ってみる ▌ホストとのファイル共有 17

  18. よく使うDockerコマンド ▌ run : コンテナの実行 ▌ stop : コンテナの停止 ▌

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

    nginx:latest # 再度、ローカルのコンテナイメージの表示 docker images 19
  20. コンテナの起動 # コンテナの起動 # -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 20
  21. コンテナに入ってみる # 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 21
  22. ホストとのファイル共有 # 適当な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 22
  23. Dockerベストプラクティス Dockerfile編 23

  24. Dockerfileの書き方 FROM quay.io/cybozu/ubuntu:18.04 COPY ./myapp /work/myapp WORKDIR /work/myapp RUN make

    && make install ENV PATH /usr/local/bin CMD [“myapp”, “--opt=hoge”] ベースとなるコンテナイメージを指定 docker build時に実行する操作を記述する COPY: ホストからコンテナにファイルを コピー WORKDIR: ワーキングディレクトリの指定 RUN: 任意のコマンドの実行 docker run時に実行されるコマンドや 環境変数などを指定 24
  25. Dockerfileのベストプラクティス ▌公式ドキュメント ⚫ https://docs.docker.com/develop/develop- images/dockerfile_best-practices 25

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

  27. 野良コンテナイメージは使わない ▌野良のコンテナイメージには脆弱性や悪意のあるコードが含ま れている可能性がある。 ▌Neco推奨のベースコンテナイメージを利用しよう。 ▌Docker Official Imagesは比較的安全 ▌どれを使うにしてもよく調査する。 27

  28. Necoのベースコンテナイメージ ▌3ヶ月ごとの定期更新と、緊急性のある脆弱性が見つかった場合は即座に 対応をおこなっている。 ▌quay.io/cybozu/ubuntu:18.04 ⚫ 必要最小限のコンテナ ▌quay.io/cybozu/ubuntu-dev:18.04 ⚫ 開発に必要なパッケージを追加 ▌quay.io/cybozu/ubuntu-debug:18.04

    ⚫ デバッグに必要なパッケージを追加 ▌quay.io/cybozu/golang:1.12-bionic ⚫ Go言語の開発環境を追加 28
  29. コンテナイメージはできるだけ小さく ▌コンテナのイメージサイズが大きくなると、ディスク容量を圧 迫したり、イメージのダウンロードに時間がかかってしまう。 ▌コンテナイメージを小さくする方法 ⚫ レイヤーを意識する ⚫ multi-stage buildを使う ⚫

    小さなコンテナイメージを使う 29
  30. コンテナイメージ レイヤーを意識する FROM quay.io/cybozu/ubuntu:18.04 RUN hostname > hostname.txt RUN date

    > date.txt RUN cat hostname.txt date.txt > id.txt RUN rm hostname.txt date.txt ubuntuイメージのファイル hostname.txtの追加 date.txtの追加 id.txtの追加 hostname.txtとdate.txtの削除 RUNやCOPYを実行するたびに、read-onlyなレイヤーが 積み重なっていく。 不要な中間ファイルをレイヤーに含めると、コンテナイメージ のサイズが無駄に大きくなってしまう。 30
  31. RUNコマンドは1行で書く、不要なファイルは削除 ▌ただし、RUNの記述を頑 張ると可読性が低下して しまう。 ▌後述するmulti-stage buildを使うのであれば、 あまり気にする必要はな い。 FROM quay.io/cybozu/ubuntu:18.04

    RUN hostname > hostname.txt && \ date > date.txt && \ cat hostname.txt date.txt > id.txt && \ rm hostname.txt date.txt 31
  32. multi-stage build ▌ ひとつのDockerfileを複数のス テージに分けて記述することがで きる。 ▌ ビルド用コンテナで生成したファ イルを実行用コンテナにコピー。 ▌

    最終ステージのみがイメージとし て保存される。 ▌ ビルドに必要なツールや中間ファ イルなどが実行用コンテナに含ま れないため、イメージサイズを小 さくできる! # Stage1: build from source FROM quay.io/cybozu/golang:1.12-bionic AS build COPY ./src /work/src WORKDIR /work/src RUN go install ./... # Stage2: setup runtime container FROM quay.io/cybozu/ubuntu:18.04 COPY --from=build /go/bin / ENTRYPOINT [“/myapp”] 32
  33. 小さなコンテナイメージをベースにする イメージ名 サイズ 特徴 scratch 0B • からっぽのイメージ。libcもshellも入ってない。 • Go言語などでシングル実行可能なバイナリを作れば、イメージサイズは

    非常に小さくなり、OS依存の脆弱性も含まないためセキュア。 busybox 1.2MB • Linuxのユーティリティをシングルバイナリで提供。 • scratch同様、シングル実行バイナリのベースとして使われる。 Alpine Linux 5.6MB • 軽量なLinuxディストリビューション。 • ハマりどころも多いので利用には注意が必要。(Necoでは利用禁止) distroless 16.9MB~ • 実行に必要なものだけを持つイメージ。multi-stage buildと組み合わせて 使いやすい。 • Java, Python, Node.js用などランタイムごとにイメージが用意されてい る。 cybozu/ubuntu 103MB • Necoチームが管理しているベースイメージ。 33
  34. .dockerignore ▌COPYやADDコマンドを利用 しなくても、Dockerfileと同じ ディレクトリにあるファイル は、Dockerデーモンに転送さ れる。 ▌ビルドに不要なファイル は .dockerignore に指定して

    おこう。 # 除外するディレクトリや # ファイルのパターンを列挙 .git/ logs/* node_modules/ ./README.md 34
  35. コマンドを正しく使う ▌ADDとCOPY ⚫ ADDとCOPYはほとんど同じだが、ADDはファイルの展開 とかインターネットからファイルを取得とか、予期せぬ動 きをする場合がある。普通はCOPYを使えば十分。 ▌ENTRYPOINTとCMD ⚫ コンテナ起動時に実行するコマンドが限定されている場合 はENTRYPOINTを使う。

    ⚫ 色々なコマンドを実行して使うコンテナはCMDを使う。 35
  36. タグを正しく使う ▌Dockerイメージのタグは、容易に更新できてしまう。 ⚫ 自分たちで作っていないコンテナイメージのタグ付けルールを 理解しておくこと。 ⚫ 自分たちで作っているコンテナイメージのタグ付けルールを しっかりと決めておく。 ▌Necoチームでのタグ運用ルール ⚫

    レジストリにあげるイメージは必ず固定タグをつける。固定タ グは変更しない。 ⚫ 利便性のためにブランチのようなタグをつけても良い。 36
  37. Lintツールを使う ▌hadolint ⚫ https://github.com/hadolint/hadolint ⚫ Dockerfileの静的解析ツール 37

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

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

  40. コンテナイメージのビルド方法 ▌Dockerfileのあるディレクトリで以下のコマンドを実行 docker build -t myapp:v1.0.0 . Dockerfileのあるディレクトリパスを指定 コンテナイメージのタグを指定 コンテナイメージの名前を指定

    40
  41. サンプル ▌training-docker/02_dockerfile/helloworld ⚫ ubuntuにnode.jsをインストールして、簡単なHTTPサーバ を起動するコンテナ ▌training-docker/02_dockerfile/multi_stage ⚫ multi-stage buildのサンプル ⚫

    stage 1: Goの開発環境でプログラムをビルド ⚫ stage 2: 空のイメージに実行ファイルだけをコピー 41
  42. コンテナイメージをビルドして動かしてみる # Dockerfileのあるディレクトリに移動してビルド docker build -t hello:v1 . # Lintツールでチェックしてみる

    docker run --rm -i hadolint/hadolint /bin/hadolint - < Dockerfile # 確認 docker images docker history hello:v1 # 起動してみる docker run --r -d --name hello -p 3000:3000 hello:v1 curl localhost:3000 42
  43. Dockerベストプラクティス アプリケーション編 43

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

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

    45
  46. ステートレスにするには ▌コンテナの更新方法 ⚫ 動いているコンテナに入って更新するのではなく、Dockerfileを 更新する。 ⚫ Dockerfileを更新すると、実行されているコンテナが更新される ようなCI/CDの仕組みを構築しておくとよい。 ▌データを永続化したい場合は、Docker や

    Kubernetes のVolume 機能を利用する。 ▌docker run に --read-only オプションを指定しよう。(Volume以 外への書き込みを禁止する) 46
  47. Volumeの使い方 # 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 47
  48. ひとつのコンテナにはひとつの役割 コンテナ App サーバ 全文検索 エンジン データ ベース コンテナ App

    サーバ コンテナ 全文検索 エンジン コンテナ データ ベース ▌コンテナは役割ごとに分割する。 ▌なぜ? ⚫ コンテナイメージが再利用しやすく なる ⚫ スケールさせやすくなる ⚫ メンテナンスしやすくなる ⚫ エラー時の復旧 ⚫ バージョンアップ わるい例 よい例 48
  49. docker-compose ▌docker-composeを利用すると、 複数のコンテナの起動を管理で きる。 ▌起動・停止 ⚫ docker-compose up ⚫ docker-compose

    down ▌03_application/compose参照 49 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 volumes: etcd-data:
  50. 正しくログを出そう ▌ファイルではなく、標準出力 or 標準エラー出力にログを出す。 ▌ログのローテーションや転送は、アプリケーション側では考え なくてよい。(DockerやKubernetesが用意しているログの仕 組みに任せる) 50

  51. シグナルを処理しよう ▌docker stop コマンドを実行した場合や、Kubernetes がコン テナを終了させるときに、コンテナに SIGTERM シグナルが飛 んでくる。 ▌シグナルを処理して、アプリケーションを正しく終了させる。

    ⚫ Graceful Shutdown: 新規のリクエストは受け付けず、現 在処理中のリクエストを正常に処理してから、プログラム を終了させる。 ⚫ ライブラリやWebサーバーの機能として提供されているこ とも多い。 51
  52. ヘルスチェックの仕組みを用意する ▌コンテナが正しく動作しているかどうか確認するための手段を 用意しておこう。 ▌ヘルスチェック用のWeb APIを用意するのが一般的。 ▌DockerのHEALTCHECK機能や、Kubernetesのliveness probe機能を利用して、コンテナの死活監視がおこなえる。 52

  53. エラーが起きたら終了させよう ▌データベースに接続できなかったり、設定ファイルが間違って いるなど、アプリケーションが自力では解決できないエラーが 発生した場合は、プロセスをエラー終了させる。 ▌コンテナがエラー終了すると、Kubernetesが復旧を試みたり、 監視システムがエラーを検知して通知を飛ばすことができる。 ▌エラーが発生しているのにプロセスを動かし続けると、障害の 検出や復旧が遅れる原因になるので注意。 53

  54. 柔軟なアプリケーション設定 ▌アプリケーションの設定は、環境変数、コマンドラインオプ ション、設定ファイルなどで外部から変更できるようにして おく。 # ホストにある設定ファイルをコンテナに渡して実行する例 docker run \ -v

    /path/to/your.conf:/etc/your.conf \ myapp:latest /bin/myapp --config=/etc/your.conf 54
  55. コンテナアプリケーションを安全に動かす ▌最新のDockerを利用する ▌docker.socketファイルの扱いに注意 ⚫ docker.socketへのアクセスは root 権限に等しい ▌rootユーザーやprivilegedで実行しない ⚫ --cap-drop=allを指定して、

    必要なcapabilityを個別に指定する ▌ホストへのアクセスは最小限に ▌秘密情報をコンテナイメージに含めない ▌コンテナイメージの脆弱性チェック ⚫ Quay.ioの脆弱性チェック機能 → 55
  56. サンプル ▌training-docker/03_application/bestpractice ⚫ アプリケーションログとアクセスログをSTDERRに出す ⚫ SIGTERMを受けるとGraceful Shutdownする ⚫ ヘルスチェック用のAPIを持つ ⚫

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

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

    ⚫ 本研修で紹介したプラクティスを取り入れてみてください。 58
  59. おまけ (時間があれば) 59

  60. いろいろなコンテナランタイム ▌Docker以外にもいろいろなコンテナ技術がある。 ▌gVisor, kata-container, Nabla containerなどなど。 ⚫ コンテナとVMの境目が曖昧になってきている ▌コンテナ関連の仕様はOCI(Open Container

    Initiative)で標準 化されているので、これまでのコンテナイメージも同じように 使える。 60
  61. BuildKit ▌次世代のコンテナイメージビルドツール ▌実験的な機能なのでまだ動作が不安定 ▌ビルドのスピードが大幅向上 61

  62. 体系立てられたDockerコマンド ▌dockerコマンドが複雑になりすぎたので再編成 ⚫ docker container ⚫ docker ps -> docker

    container ls ⚫ docker run -> docker container run ⚫ docker image ⚫ docker images -> docker image ls ⚫ docker rmi -> docker image rm ⚫ docker build -> docker image build ▌でも短い方が便利なので使い続けてしまう・・・ 62
  63. 複数種類のログを出力したい ▌ひとつのアプリケーションで、エラーログ、監査ログ、アクセ スログなど複数のログを出したい場合がある。 ▌アプリケーションではログをファイルに出力する。 ▌ログの出力先はvolumeにする。 ▌volumeのファイルを読み取り、その内容を標準出力に出すコ ンテナをログの種類分だけ用意する。 ▌サイドカーコンテナパターンと呼ばれたりする。 63

  64. Container Deep Dive ▌nsenterコマンドを使ってコンテナのnamespaceに入ってみ よう。 ▌コンテナイメージをばらして、レイヤー構造の様子を見てみよ う。 ▌iptabelsやip route, brctlコマンドを使って、コンテナネット

    ワークの実現方法を見てみよう。 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