Slide 1

Slide 1 text

Dev Containers ことはじめ 失敗から学ぶ開発環境運用法 千葉工業大学機械電子創成工学科B3 川西浩嗣

Slide 2

Slide 2 text

概要 開発環境でもコンテナ使ってみたいよね!!! Moby Dock: https://github.com/egonelbre/gophers 実行環境以上に考える事が 多いのでは? 2

Slide 3

Slide 3 text

目次(TL;DR) ● 自己紹介 ● Dev Containers とは ○ なぜ開発環境にコンテナの 恩恵がほしいのか ● 開発環境と実行環境の違い ● コンテナを作成する際の基本方針 ○ あらゆるキャッシュをどんどん活用する ○ コンテナのベストプラクティスは ある程度使える 3 ● 失敗から学ぶ開発環境運用法(前編) ○ rootユーザを使うな ○ WSL2を使おう ● 失敗から学ぶ開発環境運用法(後編) ○ 過剰な固定を避ける ○ パッケージはイメージに入れない ○ RUN コマンドを無理にまとめないのが吉

Slide 4

Slide 4 text

自己紹介 - あなたはどこの馬の骨ですか? 4

Slide 5

Slide 5 text

自己紹介 ● ボカロP / プログラマみならい ○ Golang / Terraform が多め ○ 個人的には技術記事書く方が好き ● 2022年はインターンばかりの1年でした... ○ 全部AWS or GCP絡みの長期インターン ● 千葉工業大学 機械電子創成工学科 B3 ○ 情報工学が主軸の学科ではないです(念の為) ● 24卒ゆめみ入社(予定) 5 原神の好きなキャラは放浪者です...! Twitter: streamwest1629 Github: streamwest-1629 好きなゲーム: 原神 (‘23年1月現在) Twitterフォローしろ~ いいねくれ~ Profile illustrated by もこね, Gopher: ©tottie / Renée French

Slide 6

Slide 6 text

今回のスライドについて(露骨な宣伝) ● VSCode Advent Calendarで書いた Zennの記事 ● 本日の発表内容のベースの話 ○ この記事を基にスライドを作りました ● このスライド自体も公開 ○ これで発表時間が足りなくなっても安心🤗 6 原神の放浪者とは関係ないよ(たぶん) VSCode Devcontainer 放浪記

Slide 7

Slide 7 text

本日は よろしくお願いします 7

Slide 8

Slide 8 text

Dev Containersとは 8

Slide 9

Slide 9 text

Dev Containersとは (TL;DR) テーマ: 開発環境もコンテナで! 9 これだけといえばこれだけ Image: https://code.visualstudio.com/docs/devcontainers/containers

Slide 10

Slide 10 text

Dev Containersとは (TL;DR) テーマ: 開発環境もコンテナで! 10 コンテナは2020年入ってから初めて知りました Image: https://code.visualstudio.com/docs/devcontainers/containers ● 開発環境をコンテナイメージとして管理 ○ コンテナとして管理するといいことが多い ● コンテナ内に入って開発を行う ○ ソースコードをバインドマウントさせる

Slide 11

Slide 11 text

そもそもコンテナとは アプリケーションのコード・構成・依存関係を単一のオブジェクトにパッケージ 化する仕組み※ > 近年サーバーの実行環境などで用いられる 11 ※: https://aws.amazon.com/jp/getting-started/deep-dive-containers/ OS Container Engine Container Libraries Applications Container Libraries Applications Container Libraries Applications よく見る図な印象(さらに下にハードウェアとかサーバーありがち)

Slide 12

Slide 12 text

そもそもコンテナとは コンテナはDockerfile などで定義する repo: https://github.com/streamwest-1629/chatspace ※画像は抜粋 12 ● ベースとするイメージによって はパッケージマネージャーが使 えたりする ● 文法だけならシェルスクリプト に毛が十何本か生えた感じ これは実行環境用につくったDockerfile

Slide 13

Slide 13 text

(一般的に)なぜコンテナを使いたいのか ● コンテナ以外に依存関係がない ○ コンテナイメージだけで全機能が完結している ○ コンテナの実行環境によって「あのライブラリがない」 「あのバージョンがない」がなくなる ● 移植性が高い ○ 一度記述すればどこでも何台でも実行できる ○ ローカルテストも本番環境での実行も同一の動作が期待できる 13 コンテナじゃないとどんな依存関係があるのかわからなくて不安になりますね...

Slide 14

Slide 14 text

(個人的に)なぜコンテナを使いたいのか ● 環境の構築方法がすべて記述される ○ Dockerfileに構築方法を記述するため, 「どうやって環境構築するんだっけ?」がなくなる ● ファイル管理がしやすい ○ 基本的にはソースコードと同一の方法で 管理・編集ができる ○ Dockerfileはソースコードと同様に,Gitなどの 管理下に置くことで一緒にバージョン管理ができる ● プロジェクトごとに最適な環境を用意できる 14 Linux,コンテナから入りました

Slide 15

Slide 15 text

なぜ開発環境にコンテナの恩恵がほしいのか 1. 移植性が高い →複数人・複数マシンに同一の環境を提供できる 2. Dockerfileに手順をすべて記述する →Dockerfileが環境構築のためのドキュメントを兼ねる 3. 管理がしやすい →メンバーで開発環境を 容易に共有していくことができる 15 Dev Containerを入れてから色々な言語を容易に触れるようになりました

Slide 16

Slide 16 text

Dev Containerを使う前に何があったのか ● マシンを新調・初期化する際に同一の環境構築ができなかった ○ そもそも何を入れていたのか覚えていない ○ どうやってインストールしたのか覚えていない ○ バージョン違いをインストールしてしまった ○ 同一のものを入れても期待していた動作と違う ■ 依存関係が異なっているなど ● プロジェクトごとに期待している開発環境が違う ○ そのプロジェクトに必要な自作ツールがあったりする ○ プロジェクトごとに使用しているバージョンやライブラリが違う ○ VSCode拡張機能が衝突して想定外の動作をする 16 Dev Container導入前は色々なゴタゴタがありました

Slide 17

Slide 17 text

実行環境と開発環境の違い 17

Slide 18

Slide 18 text

実行環境と開発環境の違い 18 OS/ランタイム/ 共有ライブラリ等 コンパイラ・ ビルドツール等 デバッガ・ CLIツール等 開発支援ツール等 Image: https://containers.dev/overview 同じコンテナでも実行環境と開発環境が一緒なわけないよねという話

Slide 19

Slide 19 text

開発環境のイメージは 大きくなりがち 実行環境よりも内包するツールが多い 19

Slide 20

Slide 20 text

Dev Containerのよくない話 20 なんだかんだ言ってもイメージは小さい方が楽 開発環境立ち上げ時のbuild/pullの時間が そのまま開発者全員のオーバーヘッドになる 開発環境用コンテナを開発者全員で共有する ↓ いかに短くするかが開発速度に影響する

Slide 21

Slide 21 text

コンテナを構築していくうえで大事なこと 21 開発環境のイメージは大きくなりがち 取捨選択の場面が非常に多い なんだかんだ言ってもイメージは小さい方が楽

Slide 22

Slide 22 text

取捨選択も形いろいろ ● 本当にそれは必要なツールですか? ● 本当にイメージに含める必要はありますか? 22 それぞれ吟味していく必要がある 取捨選択するとはいえ,使いたいツールは使えるようにしないといけないから...

Slide 23

Slide 23 text

コンテナを作成していく際の基本方針 23

Slide 24

Slide 24 text

コンテナを作成していく際の基本方針 ● 使えるキャッシュはどんどん使っていく ○ イメージに入れなくていいものは入れない ● Dockerのベストプラクティスはある程度有効 ○ 特に積極的にマルチステージビルドを使っていきたい 24 開発環境のイメージは大きくなりがちだから取捨選択の必要がある マルチステージビルドをかなり意識して使っていきたい

Slide 25

Slide 25 text

使えるキャッシュはどんどん使っていく ● コンテナのビルドは時間がかかるし、イメージは小さくしたい 積極的にキャッシュを使っていくことが重要 ● どのようなキャッシュがあるか a. Docker レイヤーキャッシュ (DLC)などのビルド時に使えるもの ■ これは後述 b. ボリューム・バインドマウントなどでイメージ外からマウントす るもの 25 果たしてこれはキャッシュというのか?

Slide 26

Slide 26 text

イメージ外からマウントするタイプのキャッシュ ● 別にパッケージやライブラリを管理・バージョン固定する仕 組みがあればそれに越したことはない ○ pipやnpm, go modulesなど ● 大事なのは単にコンテナで依存関係の固定ではなく、 仕組み自体と動作可能な環境があることを保証し、 仕組みに応じた最適な環境を提供すること 26 「それをキャッシュとは呼ばんだろ」というツッコミはなしでお願いします コンテナだけでライブラリを固定する必要はない

Slide 27

Slide 27 text

Dockerのベストプラクティスはある程度有効 ● キャッシュを活かす事が最優先 ● 一方でレイヤーは少ないに越した ことはない ● 並行して行えるなら 並行していきたい 27 キャッシュを活かしつつ、ベストプラクティスを模索する base publish downloader/builder 並行して作業できるならそれに越したことはないけれど無理せず

Slide 28

Slide 28 text

Dockerのベストプラクティスはある程度有効 28 base publish downloader/builder ①apt-getなどを 中心に並行して進める ②レイヤーキャッシュを 活かしながら必要なツールを ビルドしたりダウンロードする ③必要に応じて ステージ数は調整する ④ビルドしたバイナリ・ ライブラリをCOPYする ⓪最低限必要な共通の ツールを入れる キャッシュも大事だし並行して行えるので一石二鳥

Slide 29

Slide 29 text

失敗から学ぶ 開発環境運用法 前編 29

Slide 30

Slide 30 text

rootユーザを使わない 30

Slide 31

Slide 31 text

大事すぎて公式ドキュメントにもある 31 今までの話はいったん横に置き... https://code.visualstudio.com/remote/advancedcontainers/add-nonroot-user

Slide 32

Slide 32 text

rootユーザを使わない コンテナはデフォルトでrootユーザを使用してい るので対策なしではrootユーザになってしまう 32 時間次第で大喜利をしたい気持ち アクセスしたファイルの所有者がrootに .gitディレクトリを含め管理者権限が必要になり、 ホスト環境でのファイルアクセスが面倒に 致命的であるにもかかわらず 個人開発では1年以上放置

Slide 33

Slide 33 text

なぜ1年も放置したのか 33 私、コンテナじゃないLinuxを使い始めてから2年も経ってないんです... ソースコードをWindowsの ファイルシステム上に置いていたため ソースコードをWindowsのファイルシステムに置いていたため、Linuxのファ イル所有者に関する情報が残らず問題にならなかった

Slide 34

Slide 34 text

WSL2を使う 34

Slide 35

Slide 35 text

WSL2を使う 35 少し前までMacのM1用にマルチプラットフォームなイメージも作っていました バインドマウントはホスト環境のリソースをマウントする方法であるため、 ホスト環境のファイルシステムによる影響は避けられない コンテナイメージは移植性があるけれど 実行時にホスト環境の影響を受けない訳じゃない

Slide 36

Slide 36 text

ファイルシステム絡みの問題 ファイル変更イベントが走らないのでホットリロードが機能しなかった 36 これを機に開発環境をWindowsからWSL2へ切り替えました

Slide 37

Slide 37 text

失敗から学ぶ 開発環境運用法 後編 37

Slide 38

Slide 38 text

過剰な固定を避ける 38

Slide 39

Slide 39 text

過剰な固定を避ける ● 複数の方法で固定(バージョンなど)を行うのは無意味 ● 最適化された方法があるならそれを使う方がいい 39 無意味なことはしない,大事 コンテナだけでライブラリを固定する必要はない

Slide 40

Slide 40 text

過剰な固定を避ける ● 別にパッケージやライブラリを管理・バージョン固定する仕 組みがあればそれに越したことはない ○ venvやnpm, go moduleなど ● 大事なのは単にコンテナで依存関係の固定ではなく、 仕組み自体と動作可能な環境があることを保証し、 仕組みに応じた最適な環境を提供すること 40 大事なことなのでもう一度 コンテナだけでライブラリを固定する必要はない

Slide 41

Slide 41 text

パッケージはイメージに入れない 41

Slide 42

Slide 42 text

パッケージはイメージに入れない 42 これが悪夢の始まりでした Dockerfileでパッケージのダウンロードを定義 「せっかくだしパッケージ丸ご とイメージに入れれば?」 「実行環境と同じでオッケ~」 (長いので抜粋)

Slide 43

Slide 43 text

パッケージはイメージに入れない これが悪夢の始まりでした lockファイル更新毎に 全パッケージ再インストール・再追加 普通のライブラリでも十分問題だが 機械学習用ライブラリでやらかした →常にtorch再インストールの日々 →レイヤーキャッシュ大量発生

Slide 44

Slide 44 text

イメージに入れたくないけど存在を担保する方法 わかりやすいのは大事 ● 「npm ci」「pip install -r requirements.lock」などをコンテナ実行毎に呼び出せ ばいい ● venvやnode_modulesを使ったり,ボリュームで永続化させたりすることで実行時間 を縮める事が可能 ○ ボリュームの場合はディレクトリ(ファイル)の所有者の変更が必要 ● Dev Containersにはコンテナ実行毎に任意のコマンドを実行するオプションがある (postStartCommandなど) コンテナ立ち上げ時に呼び出すしかない 過剰な固定を避けることで毎回実行する代わりに,イメージ を小さくすることができてキャッシュを柔軟に設定しやすい

Slide 45

Slide 45 text

RUNコマンドは無理にまとめないのが吉 45

Slide 46

Slide 46 text

RUNコマンドは無理にまとめないのが吉 46 一般的にはレイヤーを少なくする方がよいです レイヤーを1個にしようと四苦八苦した 「レイヤーは少ないに越したことはないでしょ」 「COPYコマンドまでは全部1レイヤーに収めよう」 Dockerfileからビルドしていたため ツールを一個追加するたびにapt-getから全部やり直し

Slide 47

Slide 47 text

RUNコマンドは無理にまとめないのが吉 Dockerfileからbuild vs イメージをpull はどちらも一長一短な印象 ● Dockerfileからビルドしていく場合は特に レイヤーキャッシュを活かしていきたい ● コンテナレジストリからイメージをpullする場合は悩ましいが 悩む前に一度,マルチステージビルドで解決するかどうかを検証 レイヤーは少ない方がいいが キャッシュを活かせる方も大事 無理に分けるのではなく,機能ごとにレイヤーを分けるのが肝要

Slide 48

Slide 48 text

まとめ ● コンテナを作成する際の基本方針 ○ あらゆるキャッシュをどんどん活用する ○ コンテナのベストプラクティスは ある程度使える 48 ● 失敗から学ぶ開発環境運用法(前編) ○ rootユーザを使うな ○ WSL2を使おう ● 失敗から学ぶ開発環境運用法(後編) ○ 過剰な固定を避ける ○ パッケージはイメージに入れない ○ RUN コマンドを無理にまとめないのが吉

Slide 49

Slide 49 text

Dev Containers ことはじめ 失敗から学ぶ開発環境運用法 ご清聴ありがとうございました