はじめまして、アイキューブドシステムズでCLOMOのサーバーサイド開発を担当している YusukeIwakiです。CSEという、CLOMOの改善や維持管理をするチームで開発を進めています。
ブログを通して、「中の人はこんな感じで働いている会社だよ」という発信をしたいとずっと思っていました。このたび会社としてブログを書いていくことになったので、第1号記事を書かせていただきます!!
今回は、少し昔の話になってしまうのですが、私が昨年入社して最初に取り組んだ開発環境のDocker化の話を書いていきます。
開発環境の構築手順書がメンテナンスされていない問題
エンジニアとして入社して最初のイベントと言えば、開発環境の構築ですね。
CLOMOは大部分がRuby on Railsで作られているのですが、私の入社時、開発環境の構築手順書のようなものはあまりメンテナンスされていない状態でした。
一括で環境セットアップしてくれるansibleスクリプトは一応ありましたが、それも「ここの部分は、今はもう使われてないやつなのでコメントアウトして…」のような補足がたくさん必要とされる状態のものでした。
世の中的には「READMEくらい書いておけばいいのに?」とか思われるかもしれません。
それはそうなのですが、私が入社した時期は、サーバサイドエンジニアの採用がそれほど頻繁ではなかった時期ということもあり、構築手順書はメンテナンスされていなくても納得するしかありません。
とはいえ、ともかく環境構築手順が曖昧な状態は、今後も新規メンバーが参入することを考慮すると望ましくありません。環境構築手順が自然とメンテナンスされる状態を考える必要がありました。
macOSをアップデートすると何かが壊れる問題
MacBookを使ってRailsベースの開発したことがある人なら一度は経験があるでしょう。
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
よくネタにされるのはNokogiriですが、macOSのアップデート時に開発環境が壊れてしまうのは大きなストレスです。
前職では私はずっとLinuxを開発環境として使っていて、なるべくMac上には開発環境を構築しないようにしていました。周りには、Dockerで開発環境を作っている人もいました。
いっぽう、弊社ではみんなMac上に環境構築をしていて、「OSアップデート時に環境こわれたりしませんか?」と聞いてみると、「あぁ、壊れるね」という回答が返ってくるような状況でした。
私自身が「OSアップデートするたびに開発環境が壊れて対処する」仲間入りするのは心底抵抗があり、とはいえMDMの仕組みは何も知らないのに勝手にLinuxで環境を作って開発環境の差異要因でハマる&誰のサポートも受けられないのも嫌です。
みんなが使えるMac上で、だけどOSアップデートには影響受けないような開発環境を作る必要がありました。
そこでDocker!!
本題です。
イマドキの事情を考えても、私の過去の経験を踏まえても、社内の開発環境の課題を考えても、開発環境のDocker化は合理的な解決手段でした。
なぜVMやVagrantを採用せず、Dockerを採用したか?
たとえばRubyのバージョンアップをしたいと思ったときに、Dockerだと自然に「DockerfileのFROMを書き換えて再ビルドしよう」という発想になりやすいですが、VMだと「ansibleなりVagrantなりで作ったレシピを書き換えて対応しよう」という発想にはなりづらいです。
- VMやVagrantだと、「古い環境ベースで
rbenv install
し直す」のように、入社時とは別の手順でRubyアップデートできてしまう - Dockerを利用すると、データボリュームで永続化していない部分は基本的に使い捨てられるため、必然的に入社時と同様の環境再構築が必要になる
今回は、冒頭でも書いたように "環境構築手順が自然とメンテナンスされる状態" を作りたかったので、後者のDockerを利用するほうが理にかなっていると判断しました。
1日がかりだった開発環境セットアップは2時間で終わった
表向きの理由はいろいろ並べてきましたが、実は最初から「趣味で使っていたRails用のDockerfileを少し書き換えれば、ansibleスクリプトに頼らずとも1時間くらいで開発環境はセットアップできるのでは?」と思っていました。
とくに秘匿情報はないので公開しますが、Dockerfileはこんな感じで、趣味のWebサービスで使っていたのものをほぼそのまま、Rubyバージョンのところだけ書き換えて…
FROM ruby:2.3.3 ENV LANG C.UTF-8 RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - RUN set -x && \ apt-get update && \ apt-get install -y --no-install-recommends \ build-essential \ cmake \ git \ less \ nodejs && \ rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/* ENV ENTRYKIT_VERSION 0.4.0 RUN wget https://github.com/progrium/entrykit/releases/download/v${ENTRYKIT_VERSION}/entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \ && tar -xvzf entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \ && rm entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \ && mv entrykit /bin/entrykit \ && chmod +x /bin/entrykit \ && entrykit --symlink RUN mkdir -p /usr/src/app WORKDIR /usr/src/app EXPOSE 3000 RUN bundle config build.nokogiri --use-system-libraries ENTRYPOINT [ "prehook", "bundle install", "rm -f tmp/pids/server.pid", "--" ]
docker-compose.ymlは完全に趣味のWebサービスのものをコピペで
version: '3' services: mysql: image: mysql:5.7 volumes: - mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: hogehoge web: build: . environment: MYSQL_HOST: mysql MYSQL_USERNAME: root MYSQL_PASSWORD: hogehoge depends_on: - mysql links: - mysql volumes: - .:/usr/src/app - bundle-data:/usr/local/bundle command: bundle exec rails s -p 3000 -b 0.0.0.0 volumes: mysql-data: driver: local bundle-data: driver: local
という感じです。(蛇足ですが、Rubyのバージョンは今はもう少し新しいですw)
そうすると、CLOMOは素直なRailsアプリだったので、実際に1時間ほどでログイン画面をブラウザで見るところまでは到達しました。初期データの投入まわりで少々詰まりましたが、セットアップ自体は2時間ほどで終わったと思います。
Docker化を、既成事実を作って少しずつ広めていく
さて、私の開発が無事にDocker化されたところで、一番大切なのは、みんなに使ってもらう事です。みんながmacOS上で開発を続けている限り、環境構築手順のアップデートはDockerを使っている私だけがやることになってしまいます。
だからといって、いきなりみんなに「古い開発環境は捨てて、Docker使ってください」と強要するのも乱暴です。何の理由もなく開発環境を変更すると、逆に反感を買ってしまいます。
そこでDocker化を広めていく際には、以下の二本立ての作戦でいくことにしました。
- 「Dockerを使いたくなったら私に言ってください。全力でサポートします!!」という協調的なスタンスでいく
- 「あれ?もしかして私もDocker使ったほうがいいのでは?」と思わせるような既成事実を、ゆるゆると作っていく
まずは1人に使ってもらった
タイミングよく、協力会社の方がチームに入ってきたため、環境構築はDockerのほうでやってもらいました。Dockerの経験は全く無い方ですが、4〜5時間ほどで開発が始められる状態にはなりました。一部のエンジニアから「あれ?もう開発始められるようになったの?」という声が聞けたところで作戦成功です。
「Docker? なにそれおいしいの?」から「Docker? なんかよくわからないけど、使うと便利そう」 への認識改革です。
手順書はREADMEで書いていたものの、このときはまだ改善すべきところがかなり多く、Pull Requestでフィードバックする形を取りました。
このとき、まだまわりでは誰もDockerの開発環境を使っていないので、レビューは社内でDockerに詳しい、もしくはDocker好きな人々に声をかけて行いました。
「Docker? なんだか便利そう」から「そろそろ自分もDockerっていうのを知っておかないといけないのかな…?」 への認識改革です。
Rubyバージョンアップを機に、Docker化しようぜ!会を開いた
社内のエンジニアは、実はほとんどDockerを知っています。 知っていても、移行コストと天秤にかけて使っていないだけでした。
きっかけさえあれば移行はするだろうと思い、Rubyバージョンアップのタイミングで私が所属しているチームメンバーからDocker化を進めました。
やった内容は、単純にREADMEに従って環境構築をして、実際にRSpecを流してもらうだけです。ここでもまた、フィードバックポイントはPull Requestを通じておこない、改善につなげました。
私だけしか使ってない状況だとGit管理されていても困らなかったのが、みんな使い始めたら困るのでGit管理から外そう、という内容です。 少しずつDocker化の広まりを感じられますね…!
macOSバージョンアップを乗り越えた
Docker化が広まってきたところで、タイミングよくmacOS Catalinaがリリースされました。とりあえず私が人柱になって、OSアップグレードでDocker化の力試しをしてみました。
結論から言うと、残念ながら開発環境は壊れました…。ファイルシステム同期の高速化のために使っていたdocker-syncが原因で1〜2時間ほどハマりました。当時の格闘の結果は Qiitaに書き残しています。
ただ、逆に言うとdocker-syncしか壊れなくて、 bundle install
やRails起動などはそのまますんなりできました。新規でDockerやdocker-sync入れる人には影響なかったので、こんな感じで社内Wikiに書いて共有するだけで済みました。
macOSアップデートのたびに開発環境が壊れる問題は完全には解決できなかったものの、今後はMacにスクリプトエンジンは同梱されなくなるという噂もあるので、Docker化による貢献はできたと考えています。
Docker導入による課題
良かったことばかりを書いてきましたが、Docker化することで不満も出てきました。
多かったのは以下の2点です。
- 全体的に動作が重い
docker-compose up
してRails起動まで(macOS上でやっていた頃に比べて)時間がかかる- Macbookが(物理的に)熱くなる
- DockerがCPUリソースを食いつぶしてしまう
- Dockerデーモンの再起動で直るが、慣れていないと再起動が必要であることすらわからずハマる
動作が重いのは結構大きな課題で、たとえばこの非効率が原因で1日5分無駄にしてしまうと年間で20時間くらいは損をする計算になります。
現状だと、RubyのバージョンアップやmacOSのバージョンアップ時にDockerを使わずRails開発環境再構築するほうがコストはかかるため、Docker化のメリットを享受できています。
しかし、今後もし開発プロセスが変わってDocker化によるオーバーヘッドのほうが大きくなってしまうことがあれば、思い切ってLinuxで開発するようにするなどの見直しが必要かなと考えています。
まとめ
ブログ第1段記事として、開発環境をDocker化したことで新入社員のセットアップをラクにできたというお話をしました。
実際に運用してみて、入社して環境構築を数時間で終わらせて「さぁ開発するぞ!」ってスムーズに始められるので、新入社員の開発組織に対する印象も大幅に改善することができました。
CLOMOの開発環境にはまだまだ改善すべき点はありますが、今後も少しずつ改善して、お客様に価値を届けやすい開発環境を作っていければと思います。