この記事はのブログリレー17日目の記事です。
こんにちは。19Bの@mazreanです。
突然ですが、鯨好きですか?私は大好きです。
家で飼いたいですね。というわけで、traP内で鯨の飼い方についての講習会をしました。
本題
と、茶番はここまでにして本題に入ります。
今回は鯨(Docker)についてのより深い理解を得るための講習会をした話をしていきます。
この講習会を開くきっかけはとある勉強会についての記事を見たことです。
Container build meetupという勉強会について書かれた https://dev.classmethod.jp/articles/docker-build-meetup-1/ の記事なのですが、この記事を見て「dockerのbuildだけでここまで話せるのか」とものすごく感動しました。
今回の講習会はdockerのbuildの魅力をdockerを使い始めた新入生にも伝えたい、というモチベーションで企画しました。
講習会の対象
traPではこの講習会の前にDocker講習会という講習会が行われました。
このため、今回の講習会ではその講習会でやった程度のこと、具体的にはDockerfile、docker-compose.yamlを書いて基本的なアプリケーションをDockerにのっけることが出来る程度の知識を持っていることを前提としています。
また、受講者に新入生が多い想定(実際はそこまで多くならなかったのですが…)だったので、Docker講習会の内容の復習をちょくちょく入れました。
期間
8/29,30日の15:00から17:30に行いました。
当初は1日でやる予定だったのですが、いろいろ内容を考えているうちにやりたいことが多くなってしまったので2日に分けました。
やっていたときはあまり意識していなかったのですが、5時間もやっていたんですね…
形式
新型コロナウイルスの関係で対面では出来ないので、基本的にYoutube Liveでのオンラインにしました。
2日目には実習を最後につけたので質問対応が円滑に出来るように実習に入ったタイミングでZoomを使うようにしました。
内容
imageやdockerデーモンなどの中身を理解して、最適なDockerfileを書けるようになることを目標にしています。
そのため、1日目に理解の前提となるOCIによる標準化やDockerの熱ワークなどの話をして、2日目にDockerfileを書くに当たって考えるべきことを解説するような形式にしました。
以下ではそれぞれの日にやった具体的な内容について説明します。
資料をかなり作り込んでいるので詳しい内容は理療をご覧ください。
1日目
- Dockerとは
- コンテナ型仮想化
- Dockerの構造
- network
- volume
- Docker in DockerとDocker outside of Docker
1日目は主にDockerというアプリケーションの中身について解説しました。
序盤はOCIによるコンテナ型仮想化の標準化、その中でrunc、containerd、dockerd、Docker Clientの果している役割などを中心に解説しました。
runcの説明では直にruncを使ってコンテナを立てたりもしてみたのですが、これに関しては自分も初めてやったので自分自身もかなり勉強になりました。
中盤はdockerのネットワーク・ボリュームの理解をより深める内容になっています。
普段は見ることのないdockerによって作られたvethなどを実際に見てみることによってdockerのネットワークに対するより深い理解を得られるような内容にしています。
ここの部分はLinuxの知識がある程度無いとついていけない状態になってしまい、それなりの人数がついていけていなかったように感じられたのが心残りです。
最後にはDocker in DockerとDocker outside of Dockerについて解説をしました。
この部分は今回の講習会の中心の内容からは外れてしまっているのですが、SysAdで現在運用されているShowcaseというPaaSを作り直すプロジェクトがあり、そこでDocker outside of Dockerを利用する予定だったため入れました。
2日目
- 良いDockerfileとは
- imageの形式
- Dockerfileとlayer
- キャッシュ
- base image
- マルチステージビルド
- BuildKit
- buildの流れ
- layerの分析
- 小技集
2日目はdockerのbuildを極めていきました。
正直この日のために1日目をやっていたようなところがあり、自分自身でかなり楽しみながら準備をしていました。
まずは、良いDockerfileとは、ということについて考えていきました。
基本的なことですがDockerfileをチューニングするに当たっては重要なことだと思うので最初に入れました。
次にOCIのImage Specifiationで定められているimageの形式について話しました。
ここでは実際にimageのtarを解凍して中身を見ていきながら説明していきました。
実はこの内容は1日目に入れようとしていたのですが1日目の準備が間に合わずこちらに移していたりします。
結果的にはその後のDockerfileとimage内のlayerの関係の話にうまく繋がり、2日めに入れて正解だった気がします。
ここまでは理論部分を話してきたのですが、この後は実際にDockerfileのチューニングの実践的な内容に入っていきました。
Dockerfileからimageが作られるわけですが、Dockerfileと作られるimageのlayerの関係について解説したのが次のDockerfileとlayerという章です。
Dockerfileのチューニングをするに当たって、Dockerfileから作られるimageのlayer構造をイメージできることは重要です。
この章はこれが出来るようになるように意識して進めました。
次の章ではDockerのbuild時のキャッシュについて話しました。
キャッシュを効かせるのはbuildを速くするに当たって最も重要なポイントです。
キャッシュを出来る限り効かせるための手法を解説しました。
base imageの章ではDockerのベースイメージの種類とその使い分けについて解説しました。
base imageはDocker imageの使いやすさ、大きさを大きく左右する要素です。
思考停止でalpineを使うのではなく、その時々に適したbase imageを選べるよう、それぞれのimageの特徴について解説していきました。
次にマルチステージビルドについて解説しました。
この章では可読性を保ちつつ小さなimageを作ることを可能にしたマルチステージビルドを実際に利用しているDockerfileを見ることで実際に使えるように紹介しました。
次はBuildKitの紹介です。
Dockerのbuildを並列化し、大幅な高速化をもたらすBuildKitなのですが、traP内での普及率はまだあまり高くありません。
この章ではBuildKitの仕様者がより増えてほしいという思いで、BuildKitの並列化の恩恵とBuildKitのタグを紹介しました。
次の章ではdocker build
コマンドを叩いてからbuildが終わるまでの流れを説明し、それを通してdockerignoreの重要性を解説しました。
dockerクライアントからdockerdへ送るtarの中身を極力減らすことでdockerのbuildをより高速化出来る、ということについて解説し、実際にdockerignoreしておくべきものを説明しました。
最後にDockerfileのチューニングをしていくに当たって便利な解析のツールを紹介しました。
Container Build Meetupではdlayerが紹介されていたのですが、この講習会ではグラフィカルで初心者にとっても扱いやすいことからdiveを紹介させていただきました。
その後は「小技集」と題してdocker関連の知っておくと便利ないろいろな小技を紹介していきました。
COMPOSE_DOCKER_CLI_BUILDの正体についてはこの講習会の直前に知って急遽盛り込んだ内容です。
今までdocker-composeでBuildKitを使うときになんとなくつけていたので、その本当の意味を知ったときには感動しました。
座学はここまでだったのですが、この後Dockerfileのチューニングの練習問題を出してみて、それを解いてもらいました。
Dockerfileチューニングコンテスト
鯨飼いになろう講習会の最終課題として、Dockerfileのチューニングを行う課題を出してみました。
当初はISUCONのように本格的な競技が出来るようなアプリケーションを作ろうかと思っていたのですが、作っている時間がなく部内チャットtraQに手元でのbuild結果をのせるような形式にしました。
Jomonというリリース予定の会計サービスがあるのですが、このDockerfileに修正の余地があったのでこのDockerfileを荒らしたリポジトリを用意し、それのチューニングを行ってもらいました。
初期状態では
- 少しでも変更されればbuildのキャッシュが破棄される
- マルチステージビルドが一切使われていない
- buildで使った言語がimageに残っている
という考えうる限り最悪の状態にしてあり、少しでも変更がされればbuildに10分以上かかり、imageの大きさは820MBという状態にしてあります。
マルチステージビルドや要らなくなったtzdataの削除など、常識的な範疇でチューニングを行うと大きさが20MBぐらい、buildのキャッシュも大幅に効くようになります。
ここまでのチューニングは参加者のほぼ全員が出来るようになったので、今回の講習会の成果は十分あったのではないかと思っています。
その後パフォーマンスを無視してバイナリ圧縮なども活用して行くと12MB程度まで小さく出来ます。
ここまでやれた参加者は1人いました。
その後更に†黒魔術†も活用してベースイメージをscratchに変え、バイナリ圧縮のフラッグを調整、クライアントのjsからmapデータを排除すると7MB程度までimageを小さく出来ます。
ここまでやったのは講師の自分1人でした(正直実務でここまですることはないと思うので出来なくて良いと思います…)。
来年も新入生が入ってきたらこの講習会はやりたいと考えているので、来年までにはDockerfileチューニングコンテスト(ISUCON風にするなら、いい感じにDockerチューニングコンテスト、略してIDOCON?)のためのアプリケーションを開発できたらと考えています。
まとめ
今回鯨飼いになろう講習会をやってみて、講師の自分にとっても学びが多く、やってよかったと思います。
今回はオンラインという特殊な環境に苦労し至らない点もあったので、来年以降対面で出来るようになったときにもう一度開けたらよいと思っています。