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

Dev Containers ことはじめ - 失敗から学ぶ開発環境運用法

Kasai Kou
January 21, 2023

Dev Containers ことはじめ - 失敗から学ぶ開発環境運用法

Kasai Kou

January 21, 2023
Tweet

More Decks by Kasai Kou

Other Decks in Technology

Transcript

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

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

  3. 目次(TL;DR) • 自己紹介 • Dev Containers とは ◦ なぜ開発環境にコンテナの 恩恵がほしいのか

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

  5. 自己紹介 • ボカロ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
  6. 今回のスライドについて(露骨な宣伝) • VSCode Advent Calendarで書いた Zennの記事 • 本日の発表内容のベースの話 ◦ この記事を基にスライドを作りました

    • このスライド自体も公開 ◦ これで発表時間が足りなくなっても安心🤗 6 原神の放浪者とは関係ないよ(たぶん) VSCode Devcontainer 放浪記
  7. 本日は よろしくお願いします 7

  8. Dev Containersとは 8

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

  10. Dev Containersとは (TL;DR) テーマ: 開発環境もコンテナで! 10 コンテナは2020年入ってから初めて知りました Image: https://code.visualstudio.com/docs/devcontainers/containers •

    開発環境をコンテナイメージとして管理 ◦ コンテナとして管理するといいことが多い • コンテナ内に入って開発を行う ◦ ソースコードをバインドマウントさせる
  11. そもそもコンテナとは アプリケーションのコード・構成・依存関係を単一のオブジェクトにパッケージ 化する仕組み※ > 近年サーバーの実行環境などで用いられる 11 ※: https://aws.amazon.com/jp/getting-started/deep-dive-containers/ OS Container

    Engine Container Libraries Applications Container Libraries Applications Container Libraries Applications よく見る図な印象(さらに下にハードウェアとかサーバーありがち)
  12. そもそもコンテナとは コンテナはDockerfile などで定義する repo: https://github.com/streamwest-1629/chatspace ※画像は抜粋 12 • ベースとするイメージによって はパッケージマネージャーが使

    えたりする • 文法だけならシェルスクリプト に毛が十何本か生えた感じ これは実行環境用につくったDockerfile
  13. (一般的に)なぜコンテナを使いたいのか • コンテナ以外に依存関係がない ◦ コンテナイメージだけで全機能が完結している ◦ コンテナの実行環境によって「あのライブラリがない」 「あのバージョンがない」がなくなる • 移植性が高い

    ◦ 一度記述すればどこでも何台でも実行できる ◦ ローカルテストも本番環境での実行も同一の動作が期待できる 13 コンテナじゃないとどんな依存関係があるのかわからなくて不安になりますね...
  14. (個人的に)なぜコンテナを使いたいのか • 環境の構築方法がすべて記述される ◦ Dockerfileに構築方法を記述するため, 「どうやって環境構築するんだっけ?」がなくなる • ファイル管理がしやすい ◦ 基本的にはソースコードと同一の方法で

    管理・編集ができる ◦ Dockerfileはソースコードと同様に,Gitなどの 管理下に置くことで一緒にバージョン管理ができる • プロジェクトごとに最適な環境を用意できる 14 Linux,コンテナから入りました
  15. なぜ開発環境にコンテナの恩恵がほしいのか 1. 移植性が高い →複数人・複数マシンに同一の環境を提供できる 2. Dockerfileに手順をすべて記述する →Dockerfileが環境構築のためのドキュメントを兼ねる 3. 管理がしやすい →メンバーで開発環境を

    容易に共有していくことができる 15 Dev Containerを入れてから色々な言語を容易に触れるようになりました
  16. Dev Containerを使う前に何があったのか • マシンを新調・初期化する際に同一の環境構築ができなかった ◦ そもそも何を入れていたのか覚えていない ◦ どうやってインストールしたのか覚えていない ◦ バージョン違いをインストールしてしまった

    ◦ 同一のものを入れても期待していた動作と違う ▪ 依存関係が異なっているなど • プロジェクトごとに期待している開発環境が違う ◦ そのプロジェクトに必要な自作ツールがあったりする ◦ プロジェクトごとに使用しているバージョンやライブラリが違う ◦ VSCode拡張機能が衝突して想定外の動作をする 16 Dev Container導入前は色々なゴタゴタがありました
  17. 実行環境と開発環境の違い 17

  18. 実行環境と開発環境の違い 18 OS/ランタイム/ 共有ライブラリ等 コンパイラ・ ビルドツール等 デバッガ・ CLIツール等 開発支援ツール等 Image:

    https://containers.dev/overview 同じコンテナでも実行環境と開発環境が一緒なわけないよねという話
  19. 開発環境のイメージは 大きくなりがち 実行環境よりも内包するツールが多い 19

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

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

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

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

  24. コンテナを作成していく際の基本方針 • 使えるキャッシュはどんどん使っていく ◦ イメージに入れなくていいものは入れない • Dockerのベストプラクティスはある程度有効 ◦ 特に積極的にマルチステージビルドを使っていきたい 24

    開発環境のイメージは大きくなりがちだから取捨選択の必要がある マルチステージビルドをかなり意識して使っていきたい
  25. 使えるキャッシュはどんどん使っていく • コンテナのビルドは時間がかかるし、イメージは小さくしたい 積極的にキャッシュを使っていくことが重要 • どのようなキャッシュがあるか a. Docker レイヤーキャッシュ (DLC)などのビルド時に使えるもの

    ▪ これは後述 b. ボリューム・バインドマウントなどでイメージ外からマウントす るもの 25 果たしてこれはキャッシュというのか?
  26. イメージ外からマウントするタイプのキャッシュ • 別にパッケージやライブラリを管理・バージョン固定する仕 組みがあればそれに越したことはない ◦ pipやnpm, go modulesなど • 大事なのは単にコンテナで依存関係の固定ではなく、

    仕組み自体と動作可能な環境があることを保証し、 仕組みに応じた最適な環境を提供すること 26 「それをキャッシュとは呼ばんだろ」というツッコミはなしでお願いします コンテナだけでライブラリを固定する必要はない
  27. Dockerのベストプラクティスはある程度有効 • キャッシュを活かす事が最優先 • 一方でレイヤーは少ないに越した ことはない • 並行して行えるなら 並行していきたい 27

    キャッシュを活かしつつ、ベストプラクティスを模索する base publish downloader/builder 並行して作業できるならそれに越したことはないけれど無理せず
  28. Dockerのベストプラクティスはある程度有効 28 base publish downloader/builder ①apt-getなどを 中心に並行して進める ②レイヤーキャッシュを 活かしながら必要なツールを ビルドしたりダウンロードする

    ③必要に応じて ステージ数は調整する ④ビルドしたバイナリ・ ライブラリをCOPYする ⓪最低限必要な共通の ツールを入れる キャッシュも大事だし並行して行えるので一石二鳥
  29. 失敗から学ぶ 開発環境運用法 前編 29

  30. rootユーザを使わない 30

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

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

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

  34. WSL2を使う 34

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

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

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

  38. 過剰な固定を避ける 38

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

  40. 過剰な固定を避ける • 別にパッケージやライブラリを管理・バージョン固定する仕 組みがあればそれに越したことはない ◦ venvやnpm, go moduleなど • 大事なのは単にコンテナで依存関係の固定ではなく、

    仕組み自体と動作可能な環境があることを保証し、 仕組みに応じた最適な環境を提供すること 40 大事なことなのでもう一度 コンテナだけでライブラリを固定する必要はない
  41. パッケージはイメージに入れない 41

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

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

  44. イメージに入れたくないけど存在を担保する方法 わかりやすいのは大事 • 「npm ci」「pip install -r requirements.lock」などをコンテナ実行毎に呼び出せ ばいい •

    venvやnode_modulesを使ったり,ボリュームで永続化させたりすることで実行時間 を縮める事が可能 ◦ ボリュームの場合はディレクトリ(ファイル)の所有者の変更が必要 • Dev Containersにはコンテナ実行毎に任意のコマンドを実行するオプションがある (postStartCommandなど) コンテナ立ち上げ時に呼び出すしかない 過剰な固定を避けることで毎回実行する代わりに,イメージ を小さくすることができてキャッシュを柔軟に設定しやすい
  45. RUNコマンドは無理にまとめないのが吉 45

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

  47. RUNコマンドは無理にまとめないのが吉 Dockerfileからbuild vs イメージをpull はどちらも一長一短な印象 • Dockerfileからビルドしていく場合は特に レイヤーキャッシュを活かしていきたい • コンテナレジストリからイメージをpullする場合は悩ましいが

    悩む前に一度,マルチステージビルドで解決するかどうかを検証 レイヤーは少ない方がいいが キャッシュを活かせる方も大事 無理に分けるのではなく,機能ごとにレイヤーを分けるのが肝要
  48. まとめ • コンテナを作成する際の基本方針 ◦ あらゆるキャッシュをどんどん活用する ◦ コンテナのベストプラクティスは ある程度使える 48 •

    失敗から学ぶ開発環境運用法(前編) ◦ rootユーザを使うな ◦ WSL2を使おう • 失敗から学ぶ開発環境運用法(後編) ◦ 過剰な固定を避ける ◦ パッケージはイメージに入れない ◦ RUN コマンドを無理にまとめないのが吉
  49. Dev Containers ことはじめ 失敗から学ぶ開発環境運用法 ご清聴ありがとうございました