Dockerコンテナに開発環境を構築し、良質な開発者体験を維持した話

モノタロウのCRMグループでバックエンドエンジニアをしている新盛です。

モノタロウのCRMグループでは、主に顧客管理を中心に、フルスクラッチの基幹システムを運用しつつ、部分的にパッケージソフトや最新の技術を導入することで、増加する売上を支える事ができるシステムを目指して、システムのモダナイズに挑戦しています。

note.com

モダナイズを進めると新技術を用いたシステムを取り扱う機会が必ず訪れます。従来の業務に支障なく、新しい技術を取り入れるためには様々な工夫が必要になります。

今回は引継ぎという場面で定常業務への影響をなるべく抑えて環境構築の容易化と開発者体験の両立を実現するためにDockerコンテナが活用できた話をします。

背景

まず、引継ぎを行ったシステムについてお話します。

モノタロウは、Google Cloud Platform(以下GCP)のビッグデータプロダクトであるBigQueryにデータ基盤を構築しています。このデータ基盤は、自社の基幹システムのデータベースやパッケージソフトのデータなど、社内にあるほとんどのシステムが保持しているデータを連携しています。

tech-blog.monotaro.com

データ連携の一つとしてCRMグループが管理しているパッケージのデータ同期も行っています。データ同期のシステムは元々データ基盤グループが主管だったのですが、CRMグループで管理することになり、システムの引き継ぎを行いました。

f:id:goJuly:20220217101410p:plain

引継ぎを受けたデータ同期システムは、GCPでアプリケーションが構築されており、Cloud Runと呼ばれるサーバレスなコンテナ実行基盤で稼働しています。Cloud Run上で稼働しているPythonアプリケーションから、定期的にパッケージソフトのAPIをコールして、BigQueryへデータ同期を行う構成です。

また、Google Cloud Platformのインフラ定義はTerraformと呼ばれるオープンソースのインフラ自動構成ツールで記載されています。今回の引継ぎは、アプリケーションのソースコードだけでなく、Terraformのソースコードと、Terraformにより作成されるインフラ領域も引継ぎの範囲でした。

f:id:goJuly:20220217101440p:plain

課題

他のチームが作成したシステムを引き継ぐ際、単にソースコードを引き継ぐだけでなく、開発時のツールの利用方法やビルドデプロイの手法といった、知見のない技術を扱わなければいけないという課題に遭遇しました。

これまでCRMグループではGCP上で動作するアプリを管理したことがなく、また、Terraformを利用するために必要となるtfenvや、GoogleCloudPlatformをコンソールから操作する際にに利用するGoogleCloudSDKなど、今回のシステム開発に必要なツールを取り扱った経験もありませんでした。

そのため、他チームから引き継いだ開発手法を、私のチームで再現するには、下記のような問題を解消する必要がありました。

  • ビルド、デプロイなど開発に必要となるツールは、どのように利用するのか
  • ツールをどのようにインストールする必要があるのか
  • テストコードはどのように実行するのか
  • Windows・Mac両方で開発の動作保証をどのように行うのか

その解決策として、ビルド・デプロイのツールやテストコードの実行環境が入った仮想環境を作成しました。開発に必要なツール一式が既に入っている仮想環境を利用して開発を行うことによって、環境構築の容易化と開発者体験の両立を実現しようと考えました。

開発環境をDockerでコンテナ化するメリット

一般的に仮想環境を構築する手法として、仮想マシン(以下、VMと称する)を使った環境構築とDockerを使った環境構築があります。

VMに実行環境やコンテナを動かすための環境構築をします。既存の開発環境の構成と新しい開発環境の構成でバッティングする可能性が起こりえるため、基本的にはVMを用途ごとに分けて作ることが多いかと思います。

しかし、複数のVMを立ち上げることで、マシンリソース的に開発生産性を下げる事を懸念しました。そのため、結果的に軽量に開発環境を構築することができる開発環境をコンテナ化することが一番理想にあっており、結果的に引き継ぎ時の開発者体験をそのまま閉じ込めることが実現できると考えました。

Dockerを使った環境構築は、自身のローカルPCの環境を汚すことなく素早く環境作成のトライアンドエラーができるため、新しい技術に対する試行錯誤を簡単に行うことができます。

また、作成した開発環境をチーム内で展開できるため、環境構築の再現性を向上させることができます。環境構築の再現性が向上した事により、手順の再現のために作成するドキュメント化のコストと、それぞれのメンバーが環境構築を行う際の工数を軽減する事ができると考え、Dockerによる開発環境構築を行いました。

Dockerコンテナを用いた環境構成

今回作成した環境構成を図で表すと、以下のようになります。

f:id:goJuly:20220217101621p:plain

① 必要なツールが入ったDockerイメージの作成

Dockerfileに開発に必要なツールのインストール方法を記載して、今回の開発に必要なツールが入ったDockerイメージを作成します。ツールのインストール方法やバージョンを指定してDockerfileに記載してリポジトリで管理しているため、チーム内の開発者はDockerfileファイルをビルドするだけで、ツールのバージョンやインストール方法を意識することなく環境の構築ができます。

② RemoteDevelopmentExtensionsを利用したコンテナへの接続

VisualStudioCodeのプラグインRemoteDevelopmentExtensionsを利用して、①で作成したDockerコンテナへログインします。RemoteDevelopmentExtensionsはサーバやコンテナなど、VSCodeが実行されるホストマシンとは異なる環境に接続して、コンテナ上の環境を自身のマシンのように扱うことができるプラグインです。これにより、①で作成したDockerコンテナをVSCodeから自身のローカルマシンのように扱うことができます。

③ Dockerホストのdocker.sockファイルを①へマウント

Cloud Runでアプリケーションを実行するため、Dockerイメージの生成が必要です。この開発環境上でDockerイメージを生成できるようにするため、DockerソケットファイルをDockerコンテナへマウントしています。Dockerソケットファイルをコンテナへマウントすることで、コンテナからDockerの操作を行う手法をソケットマウントやDooDと呼びます。

Dockerコンテナのシステム要件

データ同期システムは、Cloud Runで稼働しているPythonアプリケーションであるため、アプリケーションのデプロイの際に、Cloud Runで動作させるコンテナをビルドする必要がありました。

ビルド・デプロイを行うツールをDockerコンテナへインストールしているため、開発用Dockerコンテナから、Cloud Runで動作するDockerコンテナをビルドさせる必要がありました。

DockerコンテナからDockerコンテナを操作する手法

一般的に、Dockerコンテナ上でDockerコンテナをビルドするには「Docker-in-Docker(DinD)」と「Docker-outside-of-Docker(DooD)」という二つの手法が知られています。

DinDは、DockerホストマシンのDockerエンジンとは異なる独立したDockerエンジンをDockerコンテナに持つことで、Dockerコンテナの子に当たるコンテナを作ることができるという手法です。

DooDはDockerクライアントからDockerホストのDockerエンジンへとDockerソケットを通じてアクセスする手法です。

f:id:goJuly:20220217102119p:plain

DooDを選んだ理由

DinDは、元々Dockerの開発を効率的に行う事を目的として開発された技術で、使い方に応じて高い利便性を提供してくれますが、CI/CDの用途にはDooDのほうが適していると個人的に感じました。

1.Dockerエンジンのキャッシュ利用による時間短縮

DinDのDockerエンジンはDockerホストマシンのDockerエンジンとは異なるキャッシュを保持するため、自身のマシンが持つビルドキャッシュを利用する事ができないため、初回のコンテナビルド時は時間がかかります。

一方、DooDの場合、自身のDockerエンジン上のキャッシュを利用する事ができることにより時間短縮を行う事ができるため、今回のようなビルドデプロイの用途で利用する場合は、DooDのほうが適していると感じました。

2.ソケットをマウントすることの手軽さ

DinDは実行時にDockerコンテナへ特権を付与して動作させる必要があります。DooDはDockerソケットをコンテナへマウントを行うだけで、コンテナからコンテナの操作を行う事ができるため、手軽にコンテナ操作する事ができるのも、DooDの優れている点です。

まとめ

Dockerを用いれば環境構築はもちろん、開発者体験も含めて定常業務に影響なく構築できるという話をしました。ポイントは以下の通りです。

  • 既存システムの引継ぎでDockerを利用して、開発環境を含めた引継ぎを行った。
  • 結果として、チームメンバーの環境構築とドキュメンテーション作成のコストを削減する事ができた。
  • Dockerコンテナ上でコンテナのCI/CDを行う場合、DooDの手法だと手軽にコンテナ操作が利用できた。

モノタロウでは2,000億円規模の売上を支える基幹システムを運用しつつ、新たな技術やツールを取り入れてシステムの改善、モダナイズを進めています。こうしたチャレンジングな取り組みに興味を持っていただけましたら、この記事の執筆者やシステムのモダナイズの担当者とのカジュアル面談を受け付けていますので、ご応募お待ちしています。