開発環境を Mac から EC2 に移行してみた話

この記事は 裏freee developers Advent Calendar 2018 の6日目です。 freeeでは会計の開発をしている傍ら、開発環境の改善をいろいろやっている、ソフトウェアエンジニアの @kompiro と申します。

数年放置していたこのブログですが、Advent Calendarも裏モードということで、ゆるゆるやっていきましょう。

さて、どこかで見た感じのタイトルですが、TechRachoさんのAdventCalendarにて Web開発環境をMacBook ProからWindows機に移行してみた話という記事がありました。開発環境としてのMacは、徐々に離れられているのでしょうか?栄枯盛衰ですね。

前職ではJavaのデスクトップアプリケーションを開発していました。サポートしているOSはWindowsMacだけでなくLinuxも・・・、ということだったので普段の開発環境はLinuxでした。OSに依存しない形でプラグインをパッケージングしておいたEclipseを準備しておき、僕はLinux上にそれをインストールし、その上で開発をしていました。(他のメンバーはMacWindowsにパッケージングしておいたEclipseを使っていました。)

現職は Ruby on Rails ベースのアプリケーションを開発しています。RubyMine上に開発環境を構築し、開発していました。3年前の10月に転職したので、ちょうど11月にRubyMineのライセンスが切れます。なにか他によい環境はないものか、思案してみてEC2に開発環境を移行してみました。

Q. なぜMacからEC2に移行するのか?

はやい・やすい・うまい からです。

(お客様に業務システムのクラウド化を推進する手前、ぼくらの開発環境が各々のマシンにある、というのもなんだかなぁ、と思ったりもします。)

はやい

freeeでは開発メンバー情報を管理するデータベースがあり、そこに公開鍵を登録済みであればすぐに開発用のインスタンスが立ち上がるようになっています。

今はまだできていませんが、開発用のAMIイメージを用意すれば少なくとも半日かかっていた開発環境の構築が1時間以内に終わるようになるでしょう。

やすい

開発で利用しているインスタンスタイプは t3.large の環境です。これは、Macbook Pro に立ててる docker engine に設定しているものと同等のインスタンスサイズです。このサイズだと

0.0832 USD/ h * 8h * 20 day * ≒ 13 USD / month ≒ 1500円 / month

くらいに収まります。アプリエンジニアなのでほとんどAWS触ったことがなかったので研究中ですが、 AWS Instance Scheduler というので起動・停止を制御できるみたいです。

うまい

AWSの環境にログインして操作するので、AWS_ACCESS_KEY等の払い出しは不要です。また、実行環境としてLinuxを選べるのでDockerを実行する場合のオーバーヘッドはほぼありません。

そして仮にリソースが足らないときはより大きなインスタンスに切り替えることができたり、DBを介さない処理用のサービスであればチームメンバーで共有できたり、ちょっとしたサービスであればインスタンスを立ち上げなくてもサーバレスに開発ができたり、というAWSの利点をフルに使うことができます。

昨年のre:Invent で AWS Cloud9 がリリースされ、開発環境としての EC2 に俄然興味が出てきました。今年は1年を通して開発リソースのコンテナ化と開発環境のクラウド化を進めてきました。その経験をこのAdventCalendarで共有します。

開発環境のクラウド化へと向かう道のり

表freee developers Advent Calendarで @terashi が取り上げているとおり、freeeでもマイクロサービス化を推進しています。連携するマイクロサービスの数がかなり増え、起動するのも大変になってきたので、実行にはコンテナを使うようになりました。連携サービスを Docker イメージにしておくことで、特定のバージョンをいつでも同じ環境で起動させることができます。

こうして出来上がったDockerイメージをMacで実行するには Docker for Mac を入れればOKです。Mac上に開発環境を立ち上げるのであれば Docker for Mac を入れていますが、人によってはDocker for Mac が不安定だ、という意見がありました。大抵は Docker for Mac に与えるリソースが少なすぎだったり、Docker for Macに向いていない使い方をしていたりします。

Docker for MacmacOS 上で Docker Engine が動くのではなく、 HyperKit というハイパーバイザー上で動作する、Linuxの上で動作します。 このHyperKitに与えるCPUやメモリが少なすぎたり、大量にホスト側のファイルを参照するような設定をすれば、HyperKitで動かしているコンテナは不安定になります。

Q: Docker for Mac の Docker Engineは 本当に Linux Kernel 上で動いているのか?

試しに Docker for Mac が起動する Mac 上で下記のように screen を叩いてみましょう。

$ screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty

すると

linuxkit-025000000001:~#

というような文字列が表示されます。ここでおもむろに CTRL+D を叩いてみると

Welcome to LinuxKit

                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""___/ ===
          {                       /  ===-
           ______ O           __/
                          __/
              ___________/

linuxkit-025000000001 login: root (automatic login)

Welcome to LinuxKit!

NOTE: This system is namespaced.
The namespace you are currently in may not be the root.
login[2738]: root login on 'ttyS0'
linuxkit-025000000001:~

ハロー、クジラさん、という感じで LinuxKit でビルドされたLinux imageのシリアルコンソールに接続できます。 終了は CTRL-A CTRL-K yes の順に叩きましょう。

Mac 上で docker コマンドを叩いたらこのLinux上で動いている docker engine に接続し、コンテナを起動します。

開発環境のコンテナ化をしたいのであれば、Macでのファイル編集を諦めなければならなかった

話を戻すと、大量にホスト側のファイルを参照する使い方の代表例は、開発環境のコンテナ化です。

freeeではサービスごとに開発チームがあります。それぞれの開発チームが独立した進化をするため、yarnなどのバージョンが開発チームごとに異なることがありました。普段の開発には問題ありません。しかし、隣のチームとの連携部分を開発するときに、よく支障が出ていました。

コンテナは独立した環境なので、コンテナの中に開発環境を作ることができればこの問題は起きません。一時期試していましたが結局のところMacファイルシステムをマウントするのは重すぎて断念しました。

コンテナの起動時に、Macファイルシステムをマウントしたとしましょう。すると、Mac上のファイル変更を検知したら先述したLinux側にファイルを転送します。このファイルの変更検知とファイル転送が結構な負荷をかけます。

開発環境自体をコンテナ化するにあたり、docker-sync も試しました。これもMac側のファイルシステムに大量のファイルがあるパスでは期待した高速化はできませんでした。docker-syncはあくまでDockerコンテナ内でのファイル操作を高速化するためのツールであり、Macから Linux への転送を高速化するものではありませんでした。

もし開発環境自体をコンテナ化するのであれば、ファイル転送はしないほうがいい。ということがキッカケで、僕は開発環境をLinuxベースに移行することを検討し始めました。(話が長くて申し訳ない。やっと本題に来たぞ。)

まずは Docker for Mac を引き続き使うつもりで、Linux上でファイル編集をする手段を考えてみたところ、1年前は AWS Cloud9 が出たての頃でした。買収される前のCloud9の開発用のSDKがGitHubで公開されていたのでそれを使ってみたら普通に編集ができます。 これはあくまでCloud9の拡張を開発するためのものであって、普段の開発用途で使うものではありません。しかし、発想としてこれはよさそう、と思い、 AWS Cloud9 上に開発環境を構築してみたら思いの外普通に使えそうでした。

ただ、今普段使いしているのは AWS Cloud9 ではなく、ただの tmux & vimCUI環境です。ブラウザIDEに思いを馳せてないわけじゃないんだよ。

Q, なぜAWS Cloud9(ブラウザIDE)ではないのか?

A. 東京リージョンに来てないから

え?東京リージョン来てないん・・?

... というだけじゃないんだ。

ブラウザIDEへの希望と現実

ブラウザIDEへの希望

  • どんな環境でも開発できる、たとえ iPad でもね
  • AWSにログインできればどこでも開発できる、今朝腰を痛めたから今日は家のマシンでリモート開発してもいいよね
  • 実際に実行されるコードは EC2 インスタンスだから軽い!
  • いつでも最新の環境が使える!コード補完とか名前の変更とかコードジャンプとかサクサクやろ

ブラウザIDEの現実

  • AWS Cloud9 はサードパーティクッキーがないと動かないんだ。だからそもそも iPad Pro で開発できない。ごめんね。
  • 会社のコードをいろんなところで触れたらヤバイでしょ。接続できる方法は限定しないと
  • そもそもブラウザで動いているから、ブラウザのショートカットが優先されることも多々あるんだ。例えばターミナルの上で単語を消そうと思って <CTRL+W> とか押すでしょ。するとタブごと消えるんだ・・・。
  • 例えばファイルツリーがあるでしょ?あれを描画するにはどうやってると思う?ちょっと考えてみよう

    1. ブラウザ側でツリーを開く
    2. サーバーにリクエストが飛ぶ
    3. サーバー側で指定されたツリーを ls する
    4. レスポンスを返す

    この仕組みをブラウザIDEで実現するのは結構難しい。ちょっと考えただけでもこんな課題がある。

    • 特定のフォルダの配下にいくつファイルおけるんだっけ…?
    • ファイルがたくさんある場合はブラウザにキャッシュさせればいいんじゃね?でもサーバー上のファイル名が変わってたらどう扱うんだろう。

    むずかしい。

AWS Cloud9はそんな微妙なの?

f:id:kompiro:20181205231728p:plain

微妙ではないけど、既存のプロジェクトの開発環境に使うのには向いてなさそうに思いました。なぜなら、ここ1年くらいはAWSとの統合に力を入れてたようで、基本的なIDEとしての編集機能に進化は見られませんでした。もともとあった編集環境の共有や編集履歴のトレースは強力です。AWSのアカウントで編集環境を共有できるし、IAMで権限も制限できるし、LambdaだけでなくCodeBuild等とも連携できるようになりました。でも Language Server Protocol を使ったリファクタリングや コードハイライト、プラグインみたいなIDEとしての基本機能のアップデートはあまりなかったようです。反面、AWS Lambdaのコード編集画面は Cloud9 になっててびっくりしますが。

注目のブラウザIDE: theia

f:id:kompiro:20181205231622p:plain

他にも注目しているブラウザIDEtheia ideがあります。

これはVSCodeをベースにしているのでVSCodeの拡張をそのまま使え、Language Server Protocol にも対応しているらしいです。また、GitHubリポジトリから開発環境を立ち上げられるGitPodのベースになっているので、試してみたい方はtheia ide を開き、「try theia in theia」ボタンを押してみましょう。しばらくするとtheiaの開発環境がtheia上に開きます。

theia の面白いところはVSCodeベースというだけでなく、開発を始めるときのセットアップも自動で行えたり、パッケージング方式にElectronがあるのでデスクトップアプリにできたり、というあたりです。冒頭にちょろっと「独自にパッケージしたEclipseを使ってた」と書きましたが、theiaだとVSCodeで似たようなことができそうです。

このIDEもファイルツリーが遅かったりブラウザのショートカットに殺られるという点があり、またユーザー認証は手付かずという課題はありますが、まだ0.3です。長い目で見ていきます。

Eclipse Che はどうなの?

f:id:kompiro:20181205231529p:plain
Eclipse Che

結構いい感じですよね。Eclipse Che。 正直今回はあんまり触ってないので、dockerベースで環境が立ち上がるのはよいな、としか今は言えない。このブログがEclipse扱ってたブログだったので、思い出した、という記録は残したい。

ブラウザIDEへの移行を踏まえたCUI環境の構築

とはいえ、Play with Dockerというブラウザ上でdockerに慣れるための環境があります。こいつはブラウザのショートカット以外、なんの違和感もなく使うことができます。それを実現しているのはxterm.jsです。ブラウザの上でターミナルを動かすくらいは全く苦にならない時代になりました。

Chrome AppにGoogle謹製Secure Shell App というChrome Appがあります。ブラウザでSSHするのはセキュリティの問題が残るので使っていませんが、CUIで開発できる身になればブラウザで開発できるようになるのは近い未来にできるようになりそうです。

ブラウザで開発できるようになればMacWindowsだなんだ言うことは減っていくでしょう。もっと軽くて薄いなにがしを使えるようになるでしょう。こちとら腰を痛めてるんだ、もうちょっと(物理的に)軽くなってよ、開発環境。

かくして、Eclipse改めRubyMineおじさんは CUI に再入門し、tmux & vimってこんな便利やったんや…、とかLanguage Server Protocolをおっかけているのです。

こういう開発環境や、エンジニアの開発生産性に興味があるエンジニアのみなさま、来週イベントをやるので遊びにきてくださいな。最初書くつもりだった生産性を高めるredash活用術の話をします。

明日の裏freee developers Advent Calendarはぼくらエンジニアチームを支えてくれてる yoyo さんです。