Slide 1

Slide 1 text

  devcontainer Multi Repository 戦略 2023.09.27

Slide 2

Slide 2 text

  2 2022年4⽉に freee 株式会社に新卒⼊社。 サービス基盤という部署で、社内共通ライブラリの 開発や、システム全体のボトルネックの解消、 将来のアーキテクチャ議論などに取り組んでいます。 業務では Ruby または Go を書いていることが 多いです。 不要なコードを⾒つけて消すのが好きです。 横塚 直 freee 株式会社 エンジニア Nao Yokotsuka プロフィール画像の トリミング⽅法

Slide 3

Slide 3 text

  3 Misson プロダクト開発チームが開発に専念できる環境を実現する。 ● 普段の業務 ○ バックエンド向けのライブラリ開発(主に Ruby, Go) ○ #認証 #サービス間連携 #ロギング #エラー通知 #APM ● 最近作ったもの ○ セッションキャッシュによる SPOF(単⼀障害点)問題の解消 ○ freee のマイクロサービス化を⽀える InternalSession サービス基盤について

Slide 4

Slide 4 text

  4 ● freee の全プロダクトで共通して使う仕組みの開発 ● ライブラリの開発だけしている? ○ No! No! No! ○ 作った仕組みをパイロットプロダクトに導⼊する ○ 全プロダクトに対して⼀⻫にアップデートを仕掛ける ➢ 各プロダクトを動作確認できる環境の構築が⼤変...! サービス基盤の宿命 2.何でもやれる、何でもやる 10分でわかるfreee エンジニア向け会社説明資料 Culture of Developers

Slide 5

Slide 5 text

  5 freee のプロダクトラインナップ freee会計 freeeアプリストア freeeカード freee福利厚生 freee人事労務 freee受発注 freee開業 freee会社設立 freee工数管理 freee資金調達 freee申告 freee請求書 freee販売

Slide 6

Slide 6 text

  6 ● 10 以上のリポジトリのセットアップをする必要がある ● 時期によって開発するリポジトリは変わる ● 開発環境、秘伝のタレになりがち ● 新メンバーの参⼊障壁が⾼い ● 数ヶ⽉経てばどうやって環境構築したかなど全て忘れている ➢ ⾼速かつ再現可能な開発環境が欲しい...! 環境構築のツラミ

Slide 7

Slide 7 text

  7 ● 開発環境を丸ごとコンテナ化する技術 ● かつては VSCode Extension だったが、VSCode ⾮依存な部分が OSS になっている ○ devcontainers ○ Development Container Specification ● 実装は docker コマンドのラッパー ○ devcontainer.json に書いた設定を docker コマンドのオプションに 変換してコンテナを起動してくれる 解決策:devcontainer

Slide 8

Slide 8 text

  8 ✓ 再現性 ➢ Dockerfile や devcontainer.json に必要な設定を全てを記載するため、 開発環境の構成が⾃然とコード管理される ✓ ⾼速 ➢ CI 上で docker build して registry に push すれば、各開発者はイメージを pull するだけで環境構築が完了する devcontainer が解決する課題

Slide 9

Slide 9 text

  9 ● devcontainer の最も⼀般的な使い⽅ ○ リポジトリの .devcontainer 以下に各種設定ファイルを配置する ● devcontainer.json が1つあると、開発⽤のコンテナが1つ起動する ➢ devcontainer には 1 コンテナ 1 リポジトリという原則がある 原則:1 コンテナ 1 リポジトリ

Slide 10

Slide 10 text

  10 1 コンテナ 1 リポジトリという原則を踏まえて、 複数リポジトリに跨る開発環境を devcontainer で作る⽅法 ➢ 2 つの選択肢 ① リポジトリの数だけコンテナを⽴ち上げる ② 複数のリポジトリのソースコードを詰め込んだコンテナを作る Multi Repository アーキテクチャと devcontainer

Slide 11

Slide 11 text

  11 メリット ✓ devcontainer の原則に沿っている ✓ 各リポジトリ毎に devcontainer の設定を管理できる ✓ 必要に応じてコンテナを up, down することによって 開発マシンのリソースを最適化できる デメリット ● リポジトリごとにコンテナが異なるので開発中コンテキストスイッチが 頻繁に発⽣する ➢ 同時に扱いたいリポジトリが多い今回のケースにはマッチしない ① リポジトリの数だけコンテナを⽴ち上げる

Slide 12

Slide 12 text

  12 メリット ✓ 1 コンテナで開発フローの全てが完結する ✓ 開発⽤のツールを 1 つのコンテナに集約できるのでストレージ効率が良い デメリット ● devcontainer の基本原則に反するので hacky な使い⽅が必要 ● イメージやコンテナのサイズが肥⼤化する ➢ 開発体験を重要視してこちらを採⽤! Connect to multiple containers で紹介されている構成は使い勝⼿がよくなかった ② 複数のリポジトリを詰め込んだコンテナを作る

Slide 13

Slide 13 text

  13 ● [MUST] image を pull するだけで環境構築 ● Dockerfile に以下の処理を詰め込む必要がある 1. リポジトリの clone 2. ランタイムのインストール(Ruby, Node.js, Go) 3. パッケージのインストール 4. 開発⽤ツールのインストール イメージビルドが⼤変 1 ~ 3 は ×リポジトリの個数

Slide 14

Slide 14 text

  14 ● freee で最も⼤きいリポジトリの .git は 2 GB くらいある ● リポジトリ毎に Ruby のバージョンはバラバラ ● パッケージインストールに時間がかかる ○ 特に native build が必要な gem や npm package 困難な現実 まともにビルドしたら 何時間かかるんだろう...?

Slide 15

Slide 15 text

  15 ● GitHub 社の開発⽤イメージは 35GB ○ https://github.co.jp/features/codespaces ● GitHub 社は Microsoft の傘下で Codespaces を提供するなど、 正に devcontainer 総本⼭ ● freee よりさらに⼤規模に Ruby on Rails を使い倒している企業でもある ○ GitHubは200万⾏規模のRailsアプリケーションであり、毎週RailsとRubyを最新版に アップデートし続けている 実現可能性

Slide 16

Slide 16 text

  16 ● 最終的に作りたいのは超巨⼤な Docker イメージ ● 1 つの Dockerfile を愚直に書くとツラいのは明らか ● 「困難は分割せよ」 ● リポジトリ毎にセットアップを完了させた状態の 中間⽣成物を作って最後にマージする 解決策:分割統治法

Slide 17

Slide 17 text

  17 解決策:概要図

Slide 18

Slide 18 text

  18 ● 中間⽣成物も Docker イメージとして registry に push する ● 各リポジトリのセットアップは⼤凡以下の⼿順 ○ git clone ○ ランタイムのインストール ○ パッケージのインストール ○ +α ➢ リポジトリ毎に上記⼿順を済ませたイメージを⽤意 ● COPY 命令で中間⽣成物から必要なファイルを最終成果物へ ○ ランタイムは asdf (The Multiple Runtime Version Manager) を使って インストールし、asdf の data directory をコピーする 解決策:ポイント

Slide 19

Slide 19 text

  19 Dockerfile サンプル(中間⽣成物) FROM freee-internal-base WORKDIR /home/vscode/src/repo-a RUN git clone https://github.com/org/repo-a . RUN asdf install RUN bundle install -j4 RUN npm install Ruby や Node.js がインストールされる 中間⽣成物なのでレイヤ数の圧縮は気にせずに RUN 命令は細かく分割する ローカルでビルドする際にレイヤキャッシュ を活⽤できて効率 UP apt パッケージのインストール等を済ませた ベースイメージ

Slide 20

Slide 20 text

  20 Dockerfile サンプル(最終成果物) FROM freee-devcontainer-src-images/repo-a as repo-a FROM freee-devcontainer-src-images/repo-b as repo-b FROM freee-devcontainer-base COPY --from=repo-a /home/vscode/.asdf /home/vscode/.asdf COPY --from=repo-a /home/vscode/src/repo-a /home/vscode/src/repo-a COPY --from=repo-b /home/vscode/.asdf /home/vscode/.asdf COPY --from=repo-b /home/vscode/src/repo-b /home/vscode/src/repo-b 中間⽣成物をソースに指定 これらの COPY を開発する リポジトリ全てに⾏う 開発⽤便利ツールを⾊々インストール済

Slide 21

Slide 21 text

  21 ✓ セットアップ⼿順をリポジトリ毎に切り分けて考えられる ✓ 1イメージあたりのビルド時間はそこまで⻑くない ○ ⼀番⼤きいリポジトリでも 10 ~ 20 分くらいだった ✓ 中間⽣成物の組み合わせ⽅次第で⾃由な開発環境をデザインできる ➢ 16 リポジトリを含む, 約 20 GB のイメージを作成、無事開発環境を コンテナにすっぽりと収めることができた Advantages 結果...

Slide 22

Slide 22 text

  22 ● 開発⽤の VM 起動 → devcontainer up で開発環境完成 ● Multi-root workspaces を使ってVSCode 1 window で シームレスな開発体験を実現 ● 2週間に1回くらい開発環境をスクラップ&ビルドできている ● いつ開発環境が吹き⾶んでも⼤丈夫な安⼼感 ● 新しいチームメイトにもサクッと同じ環境を作ってもらうことができた ● (副作⽤的に)freee の開発事情についてより⼀層詳しくなれた 使ってみてよかった点 作った当初は楽しくて毎⽇ やってた

Slide 23

Slide 23 text

  23 ● コンテナの中で快適に開発するためには結構リテラシーが求められる ○ Docker outside of Docker で他のコンテナを操作する etc ● 開発するリポジトリが数個の場合はオーバーエンジニアリング感がある ● ちょっとした環境変数の設定等を全てコード化していくのは⾯倒 もうちょっとポイント

Slide 24

Slide 24 text

  24 ● リポジトリ毎にセットアップして、最後にマージするという シンプルなやり⽅で freee の開発環境を 1 イメージに納めることができた ● 10 以上のリポジトリを快適に開発できるようになり、 作り直しやチームメイトへの共有も容易 ● コンテナ内で開発するためにはちょっとコツが要る まとめ

Slide 25

Slide 25 text

ご清聴ありがとうございました!