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

Docker2020

Cybozu
August 19, 2020

 Docker2020

Cybozu

August 19, 2020
Tweet

More Decks by Cybozu

Other Decks in Technology

Transcript

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

    View full-size slide

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

    View full-size slide

  3. はじめに
    3

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  8. コンテナの仕組み
    8

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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:

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide