DMM.comの、一番深くておもしろいトコロ。

ポイントサービスへ勝手にDockernize活動をやってみた

ポイントサービスへ勝手にDockernize活動をやってみた

  • このエントリーをはてなブックマークに追加

はじめまして。ペイメントサービス部 ポイントグループの柏熊です。
1年ほど前にポイントグループへ異動してきてから、システムの開発や保守・改善活動に取り組んでいます。

今回の記事ではこれまで行ってきたポイントサービスへの「勝手にDockernize活動」について、活動に至った経緯や取り組み方、活動の結果についてご紹介したいと思います。

勝手にDockernize活動とは?

柏熊が個人で取り組んできた「ポイントサービスのプロダクトを勝手にDocker化(dockernize)する」活動のことです。
1年ほど前に異動してきてから、これまで地味に取り組んできました。
異動当時のことを思い出しながら、今に至るまでを整理してお伝えしようと思います。

--

ポイントシステムは数十年前に発足し、これまでのDMMのポイントサービスを支えてきました。
現行システムは、5~6年前から稼働しているものでPHP 5.4のバッチが稼働しており、今でもメンテナンスのためにコードを修正する機会があります。
コード修正時にローカル開発環境にて動作検証をするのですが、このローカル開発環境の構築において問題と感じることが3つありました。

1.準備に時間がかかる

ローカルの動作検証環境は、VM(VirtualBox)で行っていました。
このVMイメージサイズは1.3GBほどで、共用ファイルサーバから各自のPCにダウンロードする手順となっていました。
イメージサイズが大きいのでダウンロードに30分ほど時間かかかってしまい、初期構築の際はコーヒーを1杯飲むぐらいの待ち時間が発生しておりました。

f:id:dmminside:20200710151025p:plain:w200

2.起動・停止が遅い

やっとのことでダウンロードが終わったので、VMを起動しようとします。
すると、今度はVMの起動が完了して利用できるまでに数分の待ち時間が発生します。
別プロダクトの動作検証時に利用ポートのバッティングがたびたび発生することもあり、そのたびにVMの停止/起動が必要となります。
これが結構な頻度で発生しており、そのたびに待ち時間が発生します。

VMはOSを仮想的に起動させるので時間がかかってしまうのは仕方のないこととはいえ、もどかしい思いでした。

f:id:dmminside:20200710151052p:plain:w200

3.構築された手順が不明で、動かない時がある

VMのイメージにはJavaの実行環境、PHPの実行環境とMySQLがインストールされており、複雑な構成でした。
イメージ作成の手順も残っておらず、修正を加えてしまうと元に戻せません。
「ちょっと改善しよう!」と思っても、修正前にイメージ(1.3GB)をコピーしてバックアップを取っておく、という作業が必要となります。
さらに、イメージを更新した後は共有ファイルサーバにアップロードして更新する必要がありますが、もちろんこれにも時間がかかります。

f:id:dmminside:20200710151119p:plain:w150

--

これらの問題により「少し修正して動かしたい!」というモチベーションが湧いても、動作させるまでの数々の手間が頭によぎりやる気が削がれてしまっていました。
これではまずいと感じ、勝手にDockernize活動を始めました。

なぜDockerで、コンテナ化か?

ではなぜDockerを用いてアプリケーションをコンテナ化することを選んだのか。
それは「クラウドネイティブ化するための第一歩だから」です。

Cloud Native Computing Foundation(CNCF)というクラウドネイティブ化を推進する団体がクラウドネイティブ化にむけたロードマップ(https://github.com/cncf/trailmap) を公開しています。
このロードマップにおいて、クラウドネイティブ化の第一歩として "コンテナ化" がを勧められていたのが大きな理由です。
また弊チームでもかねてより、「オンプレからクラウドに移動したいね〜」という話がプロダクトオーナーからあがっていたこともあったため、これを期にコンテナ化することを決めました。

コンテナにはランタイムがいくつかあり、その中でもDockerを採用しました。
ランタイムはOpen Container Initiative(OCI)によって標準化されており、実装すべき機能やフォーマットが業界標準として定められています。
つまり、ランタイムによって大きく機能は変わらないと考え、単純に馴染みのあるDockerを選びました。

取り組み方について

ここからは、Dockernize活動にあたっての取り組み方をご紹介していきます。
なお、Dockerベストプラクティス的な話は調べるとたくさん出てくるため、本記事では私なりの取り組み方についてご紹介したいと思います(参考になるかは分かりませんが…)。

個人の時間で取り組む

Dockernize活動をするための時間をどのように捻出したか?
チームのタスクとしてやるか、個人の時間を使ってやるかという選択肢があると思いますが、私は個人の時間を使って取り組みました。
なぜかというと、弊チームには10%ルールというものがあったからです。これは勤務時間の10%を好きなことに使えるというルールです。
私はこの時間を有効活用して、個人でチームの問題を改善する時間を捻出しました。

地道にコツコツとやる

先述のとおり、現状のVMは構築内容が不明であり、どういったツールが入っていたかも分かりませんでした。
これについての対処としては「地道にコツコツとやった」としか言いようがありません。 ひたすらDockerfileを書き、docker buildし、動かしてエラーを潰すサイクルを回して進めてきました。
最初は不明なことばかりなうえにエラーまみれで辛いですが、少しずつ進めていきました。
f:id:dmminside:20200710151147p:plain:w200

ベースイメージはDockerHubで探す

Dockerイメージを作るには、最初にベースとなるDockerイメージを用意する必要があります。
Google先生に「PHP Docker 開発環境」と聞いて調べるのも良いですが、私はDockerHub(https://hub.docker.com/) で検索しました。
理由は、ブログで公開されている使い方よりも一次情報のほうが最新でイケてる使い方を見つけることができたりするからです。
また、最初から誰かが作ったイメージを使ってしまうと、実はやらなくても良い手順をやってしまっていたりするものです。
なので、個人的にはまず一次情報に触れるようにしています。

複数アプリから参照されるデータベースは、別リポジトリにする

VMにはデータベース(MySQL)もインストールされていました。
このままPHPバッチのGitリポジトリへデータベースのDocker定義を追加することも考えられますが、このデータベースは他のプロダクトからも参照されていました。
データベースは、DockerfileとMySQLの設定、マスタデータ(SQL)も保持しているため、各プロダクトのリポジトリで管理すると多重管理することになってしまいます。

f:id:dmminside:20200710151213p:plain
重複管理が発生する構成

これについては、データベース関連のみを管理するリポジトリを新設し、参照するプロダクトは、GitSubmodule機能を使ってこのリポジトリを参照する形を取りました。
GitSubmoduleを利用することで "マスタデータの一元管理" という目的を達成できます。

このままだとアプリ側のDocker、DB側のDockerネットワークが異なるため通信できません。
これについては、アプリ側のDockerネットワークを作らず、DB側のDockerネットワークを利用することで解決しました。

f:id:dmminside:20200710151306p:plain
重複の問題と通信経路の問題を解消した構成。

最善とは言えないかもしれませんが、今のところ必要十分なのでこのような対処としています。

容赦なくOSSを活用する

Dockernizeの対象にJava APIがありました。
JavaのDockernizeには Jib(https://github.com/GoogleContainerTools/jib) というOSSを使いました。
雑に説明すると、JibはDockerfileを書かずにJavaをDockernizeしてくれる頼もしいOSSです。
これを活用することで、JavaのDockernizeは1時間ぐらいで対応できました!
使えるものは容赦なく使おうという精神で臨んでいました。

取り組んだ結果

これまで、活動に至った経緯や、Dockerによるコンテナ化を選択した動機、そして取り組み方についてご紹介してきました。
ここからは、対応する前に問題となっていたことがDockernize活動によってどのように変化したかをご紹介します。

1.準備に時間がかからなくなった

VMの頃と大幅に変わって、イメージサイズは400MB程度になりました。
サイズが軽くなったぶん、イメージビルドとダウンロード時間を含めても1分ほどで完結するようになりました。
もうコーヒー休憩する余裕なんてありません。

2.起動・停止が速くなった

こちらも同じくVMの頃と大幅に変わり、起動・停止ともに3秒ぐらいになりました。
かなり速くなったので、起動・停止に面倒くささを感じなくなりました。
いくらでもポートバッティングしてくれという、寛大な気持ちになれましたね?(違う?)

3.構築された手順が明白になり、動かない原因も特定しやすい

Dockerは、Dockerfileにイメージの構築手順を書くので、どういったコマンドでイメージを構築したかが明白です。
環境によって動かないといったメンバーもいますが、構築手順が明白なので原因の特定・改善がしやすいです。
改善のためにイメージを修正する場合でも、イメージは変更内容をファイルのレイヤリングとして残しているので、修正してビルドからリトライするといったことがやりやすいです。
ローカルの開発環境をDockerfileでGithubにコミットして配布しており、各自の環境でイメージをビルドできるのでアップロードは不要になりました。
あの老舗の味を、誰でも簡単に再現できるようになりましたね?(何が?)

--

Dockernize活動に取り組んだ結果として「少し修正して動かしたい!」という場合にもつまずくことなく、スムーズに始められるようになりました。
改善したいというモチベーションを落とすことなく、楽しく改善活動をできるようになりました!

活動中に意識したこと

思い返すと、Dockernize活動を通して意識していたことがあったのでいくつかご紹介します。

EasyよりもSimpleを

ローカルのテスト環境をDockerで用意する場合にやってしまいがちなのがShell Scriptを書いて全部自動で構築できるようにする、いわゆる"全自動化"です。
賛否両論あるかもしれませんが、個人的には「なんかよく分からんけどShell Scriptを叩くといろいろやってくれて完成する(Easy)」よりも「ある程度で自動化を諦め、素直にREADME.mdなどへ手順を残す(Simple)」ほうが良いと考えています。
Shell Scriptに自動化を詰め込んでいくと「なんでもやる巨大なscript」に成長しがちです。結果として、楽をするために作り込んでいたScriptが、数年後にはメンテナンスして維持するコストが高く扱いずらいものになってしまいます。
なので私は「過度な自動化(Easy)」よりも「分かりやすく明示的な手順(Simple)」を選びました。

頑張りすぎない

今回DockernizeをしたPHPバッチにはほとんどテストが書かれていませんでした。
Dockernizeするタイミングで一緒にテストを書いても良いのですが、それはしませんでした。
理由は「単純に10%ルールの時間でこなせない」というのと「燃え尽き症候群対策」です。

所詮は個人活動のため、限られた時間ではどうしても長期戦になります。頑張りすぎて手を広げすぎてしまっては、なかなか終わらなく達成感が得られなくなります。結果、燃え尽きてしまっては元も子もありません。
私の場合は、後でできそうなことは素直に諦めて対応しました。

おわりに

少し長くなってしまったのでまとめさせていただくと、以下のようなことをご紹介してきました。

  • クラウドネイティブなアプリにするための第一歩として、Dockerによるコンテナ化がおすすめです。次の改善活動に繋げやすくなります。
  • Dockerイメージを作る時はDockerHubからベースイメージを探しつつ、便利なOSSを躊躇なく活用しましょう。
  • 完璧な自動化を目指したり、自分の時間を削りまくるようなやり方を選んだりと頑張りすぎないにしましょう。

正直、Dokcernizeをやっていた時には半信半疑でしたが、数カ月ぶりにPHPバッチを触った瞬間に感動しました。そうです、PHP 5.4でもちゃんとDockernizeされているおかげで簡単にテストが動くのです! CNCFが勧めるとおりにDockernizeをやってきましたが、こういった積み重ねが開発体験(Developer Experience)を高めることにつながっていくのだな、と実感した瞬間でした。

後日談ですが、諦めていたローカルのユニットテスト実装については勝手にDockernize活動の後に別メンバーが華麗にこなしてくれました。
始まりは個人の活動でしたが、チームメンバー間でいい感じに補い合えたので良かったなと思っています。

--

あなたの身の回りでも、どうにかしたいけど諦めてそのままにしていることはありませんか?
自分でできる範囲から、少しずつ取り組んだら何かが変わるかもしれません。

宣伝

ポイントグループでは、一緒に働いてくれる仲間を募集しています。 ご興味のある方はぜひ下記募集ページをご確認ください! dmm-corp.com