Slide 1

Slide 1 text

今さら聞けないDocker入門 Dockerfileのベストプラクティス編 日本仮想化技術株式会社 水野 源 [email protected] 2024/04/25 1

Slide 2

Slide 2 text

発表者について • 水野 源 • VTJ 技術部所属 • Ubuntu JPメンバー • ubuntu.comメンバー • 著書に「Linuxをマスターしたい 人のための実践Ubuntu」など 2

Slide 3

Slide 3 text

本日のアジェンダ • コンテナとは • Dockerとは • Docker Imageとは • Dockerfileのベストプラクティス 3

Slide 4

Slide 4 text

コンテナとは? 4

Slide 5

Slide 5 text

LinuxはマルチプロセスなOS • 現代的なOSでは、複数のプロセスを並列して動かすことができる • 複数のアプリを同時に動かせたりするのはこれのため • 1台のサーバー上に、Webサーバーとデータベースを同居させると いった使い方も一般的 5

Slide 6

Slide 6 text

マルチプロセスが抱える問題 • これらのプロセスは、OS上の同一の空間内で実行される • そのためプロセス間でOSのリソースを共有する(あるいは奪い合う) • ルートファイルシステム • NIC • IPアドレス • ポート • 名前空間 • /etc以下の設定ファイルなど • 同一のポートを使うプロセスや、OSレベルの設定や要求するライブ ラリのバージョンが異なるアプリを共存させるのは難しい 6

Slide 7

Slide 7 text

ベアメタルと仮想マシンの時代 • ならばアプリごとに専用のサーバーを用意すればいい • OSの資源を占有できるのだから、共存時にあった問題は解決する • しかしそれでは、アプリの数だけハードウェアが必要になってしまう • お金かかりすぎ…… • そこで仮想マシン • 1台の物理サーバー上で複数の仮想マシンを起動し、用途ごとの専用サー バーとして分離する方法がトレンドになった • しかし仮想マシンでは、VMごとにOSをインストールしなければならない • ひとつのアプリのためだけに、専用のVMやOSを用意するのは、管 理の手間やリソースの無駄が大きい 7

Slide 8

Slide 8 text

そしてコンテナの時代へ • プロセスを隔離した空間内で実行する技術 • プロセスは、ホスト上の通常のプロセスとは異なる空間で実行されている • 個別のルートファイルシステムやIPアドレスが割り当てられる • プロセスはあたかも独立したOS内で動いているかのように振舞える • これはLinuxカーネルのnamespaceやcgroupといった機能で実現されている • ホスト側から見れば、単にプロセスが起動しているだけ • VMよりもオーバーヘッドやパフォーマンスの低下が少ない • VM乱立の時代から、プロセス単位でコンテナに隔離する時代へ 8

Slide 9

Slide 9 text

Dockerとは? 9

Slide 10

Slide 10 text

Dockerとは • 現在世界で一番普及している(と思われる)コンテナ実行環境 • アプリケーションを開発、転送、実行するためのプラットフォーム • OSとアプリケーションを分離することで、効率のいいデリバリーを可能とする • 最近ではDockerで動かすことを前提に、構築済みのイメージや、イ メージをビルドするための設定などが開発元から配布されていること も一般的 • Docker Hubというコンテナレジストリが用意されているなど、ユー ザーにとって使いやすいエコシステムが整備されていることも人気 の理由のひとつ 10

Slide 11

Slide 11 text

Dockerのうれしいところ • ひとつのコンテナにひとつのプロセスの原則 • 仮想マシンとは異なり、プロセス単位でホストOSから分離することに特化 • イミュータブルでカプセル化されたアプリケーション実行環境 • アプリケーションのポータビリティの向上 • 同一の環境を再現できるため、開発環境/本番環境の差異の吸収 • リソースの最適化 • OSとアプリケーションのライフサイクルの分離 • メンテ効率の向上 • インフラ管理運用コストの削減 11

Slide 12

Slide 12 text

仮想マシンとの違い 12 Host OS Kernel Docker Engine App 1 App 2 Host OS Kernel Hypervisor OS 1 OS 2 App 1 App 2 Kernel Kernel 仮想マシン Docker

Slide 13

Slide 13 text

Docker Imageとは? 13

Slide 14

Slide 14 text

Docker Imageとは • 実行中のコンテナには、それぞれ個別のルートファイルシステムが マウントされる • これの元になるのがDocker Image • ただし仮想マシンイメージとは異なる • ベースイメージに対する差分を重ね合わせたレイヤー構造を取る • OverlayFS • イメージは基本的にReadOnly • 何度実行しても同じ状況を再現できる 14

Slide 15

Slide 15 text

仮想マシンイメージとの違い 15 Kernel Library Middleware Application 仮想マシンイメージ Dockerイメージ Base Image Layer Layer Layer ファイルがインストールされた実体をイメージ化 抽象的な概念

Slide 16

Slide 16 text

OverlayFSとは 16 https://docs.docker.jp/engine/userguide/storagedriver/overlayfs-driver.html より引用

Slide 17

Slide 17 text

Dockerでアプリを動かすには • アプリをインストールしたDocker Imageを事前に構築する必要がある • これを「イメージをビルドする」などと呼ぶ • Docker Imageの設計図となるのがDockerfile • Imageの構築手順を書いた設定ファイル 17

Slide 18

Slide 18 text

Dockerfileのサンプル 18 FROM ubuntu:jammy ← ベースイメージにUbuntuの22.04を使用する RUN apt-get update && apt-get install –y hello ← helloパッケージをインストールする RUN rm –rf /var/lib/apt/lists/* ← パッケージリストを削除する ENTRYPOINT 「“/usr/bin/hello”] ← コンテナ起動時に/usr/bin/helloを実行する CMD [“-g”, “hello”] ← helloコマンドのデフォルト引数 Dockerfileの例 $ docker build . –t hello ← helloという名前のコンテナをビルドする Docker Imageのビルド $ docker run --rm hello ← helloという名前のコンテナを実行する Hello ← /usr/bin/hello –g helloが実行された ビルドしたDocker Imageの実行

Slide 19

Slide 19 text

ビルドされるDocker Image 19 FROM ubuntu:jammy RUN apt-get update && apt-get install –y hello RUN rm –rf /var/lib/apt/lists/* ENTRYPOINT 「“/usr/bin/hello”] CMD [“-g”, “hello”] Dockerfile Dockerイメージ ubuntu:jammy apt-get install –y hello rm –rf /var/lib/apt/lists/* RUNやCOPYといった各種命令が、差分レイヤーとしてイメージに追加される

Slide 20

Slide 20 text

Dockerfileのベストプラクティス 20

Slide 21

Slide 21 text

Imageのダイエット • Imageの可搬性を上げるためには、少しでもImageのサイズを小さく すべき • これでpush/pullの時間が短縮できる • 効率アップだけでなく、省エネ、コスト削減に繋がる • 不要なデータが入ってると、セキュリティリスクになることもある • ビルドの仮定で発生した無駄なデータは消しておこう • さっきの例の RUN rm –rf /var/lib/apt/lists/* とかがまさにこれ • Ubuntuの公式コンテナイメージは、デフォルトでapt cleanを実行している 21

Slide 22

Slide 22 text

レイヤーキャッシュ • Dockerfile内の命令ごとに、ファイルシステムの差分を生成する • これがレイヤーになる • ビルド済みのレイヤーが存在する場合、キャッシュが再利用される • ビルドやpullの時間短縮になる • Dockerfileの上から順に命令が実行されてキャッシュされる • Dockerfileを書き換えると(←重要)、書き換えた行以降のキャッシュが作り直される • 変更されない命令から順に書くことで、キャッシュを最大限に利用できる • 逆に、更新されるべきレイヤーがキャッシュされてしまい、思った通り動かないと いった落とし穴にも注意 • キャッシュの粒度を考えてレイヤーを分割しよう • --no-cacheオプションの活用 22

Slide 23

Slide 23 text

マルチステージビルド • アプリのビルドには色々なツールが必要 • だがそれはビルド完了後は不要になる • Imageを軽量化するためにも、こうしたツールは本番コンテナから除外したい • ビルドした成果物だけを取り出して、空のコンテナで実行するのがい いのでは? • よし、ビルドコンテナと実行コンテナを分離しよう • これがマルチステージビルド 23

Slide 24

Slide 24 text

マルチステージビルド 24 Dockerfile Application Build Tool Library Source Code Build ビルド用コンテナ 実行コンテナ Application Copy ビルド用コンテナは、ビルド 完了後は破棄される ビルドしたアプリケーション だけを含んだ軽量なImage が作れる

Slide 25

Slide 25 text

Distrolessの活用 • 実行コンテナのImageには、実行時に必要なものだけが入っていればいい • 極論、それ意外のライブラリやツールは不要、というか邪魔 • Ubuntuコンテナにはapt等のツールが入ってるけど、構築が終わった後はいらない • 本当に空っぽのイメージを用意して、そこに実行バイナリだけを入れれば いいのでは? • この発想でGoogleが作ったイメージがDistroless • glibcとかlibsslとか、/bin/shすら入ってない • Distrolessはその特性から、GoやRustと相性がよい • マルチステージビルドで活用しよう • コンテナのベースOSのセキュリティとかも気にしなくてよくなる 25

Slide 26

Slide 26 text

エフェメラルなコンテナを目指す • コンテナは使い捨て可能にしよう • 永続的な情報をコンテナ内に持たせない • 機密情報は起動時に環境変数を経由して注入するなど • オンプレのような、サーバーを育てていく思想は捨てよう • 使い捨てが可能なようにコンテナを設計することで • いつでも同じ環境が再現可能になる • 環境に起因するトラブルをなくせる • 開発環境と本番環境を同一にできる • コンテナ間に差異がなくなるので、スケールアップが容易になる • 障害対応力も上がる 26

Slide 27

Slide 27 text

コンテナのセキュリティ • FROMに非公式イメージを使わない • Docker Hubにある公式イメージをベースにしよう • 非特権ユーザーを使う • USER命令はマスト • 不要なファイルを含めない • コンテナに機密情報を埋め込むとか論外である • (ベースOSが更新される場合)頻繁にビルドして更新する • CI/CDが重要 • 脆弱性チェックも活用しよう 27

Slide 28

Slide 28 text

質疑応答 28