こんにちは!株式会社OPTiMに所属しております川田剣士です。最近の業務でdockerコンテナの起動時間を3分から20秒まで1人で縮めることに成功しまして、こちらの経験を皆さんにも共有したく技術執筆をしようと思いました。記事に対する質問・コメント大歓迎です!
目次
タスクを取り組むに至った背景
今回起動時間短縮に成功したdockerコンテナをdockerコンテナAと以下で記載します。タスクを取り組むに至った背景(解決したい問題)を以下に記載します。
- dockerコンテナAを起動して内部で実装されているAPIを外部から呼び出す検証作業があり、その際にdockerコンテナAを停止・起動する機会が1日に何度もあった。停止・起動するたびに3分近く待たなければいけないという点で検証作業の効率が悪かった。
- 当時3分近くコンテナの起動にかかっていたため、オートスケールをする際にpodが立ち上がっても3分近く意味をなしていない状態であった。また、コンテナ起動に時間がかかっているため、オートスケールの際にpodが20個近く立ち上がってしまうという問題もあった。
- 障害などでpodが落ちた時のダウンタイム時間が最短でも3分近くかかっている状態であった。
上記の問題を解決するためにコンテナ起動時間をなるべく短くする必要がありました。
前提条件
前提条件を以下に記載します。
- dockerコンテナAではjava,spring bootを利用している。
- dockerコンテナAの起動時はspring-boot:runを実行して、Spring Bootアプリケーションを起動している。
- Javaプロジェクトのビルドと管理をApache Mavenを利用して行なっている。具体的には、Spring Boot Mavenプラグインを使用して、pom.xmlにSpring Bootアプリケーションに関連するいくつかのgoalを指定し、コンテナ起動時(spring-boot:runの実行)はpom.xmlに指定したgoalを実行している。
Spring Boot Maven プラグインのドキュメントを確認していただけるとイメージしやすいかなと思います。 - buildpack化はできない状態である。理由は、アプリケーションで利用しているとあるライブラリ(ここではライブラリAと呼ぶ)が特定のpropertiesファイルのみしかアクセスできず、実行環境によって読み込むpropertiesファイルを切り替えることができないからである。そのため、現状はdockerコンテナ起動時にpropertiesファイルを上書きするようなスクリプトを実行している。例えば、コンテナ起動をテスト環境で行った場合、libraryA_properties.testの内容をlibraryA_propertiesファイルに上書きしている。
- 今回のコンテナ起動時間の短縮は恒久対応ではない。恒久対応は環境ごとにpropertiesファイルの切り替えができないライブラリAを利用せず、代わりのライブラリを利用してbuildpack化することである。
dockerコンテナの起動時間が遅い原因の調査と解決方法
コンテナの起動時のログを確認したところ、コンテナ起動時間が約3分弱かかっており、そのうちcompileとtest-compileでそれぞれ1分近くかかっていました。ちなみに、compileはjavaの実装コードのcompileであり、test-compileはjavaのテストコードのcompileを行なっています。そのため、image作成時にcompile,test-compileを行い、起動時に行われるcompileとtest-compileに関してはキャッシュを利用させるようにすることで、起動時間短縮を目指しました。
対応した内容はimage作成時のコマンドに以下を追加しただけです。
RUN ./mvnw test-compile
compileはtest-compile内部で行われるため、RUN ./mvnw compileの実装は必要ないです。
後は、コンテナ起動時にダウンロードしているライブラリがあったため、ライブラリのダウンロードはimage作成時に行うように修正しました。この修正によって、ライブラリのダウンロード時間分の短縮、コンテナ起動の安定化(ライブラリのダウンロードに失敗したらコンテナの起動に失敗してしまうため)を見込めます。
その後、コンテナを起動したところ、全体としては1分30秒まで縮めることに成功したことを確認しました。そして、引き続きボトルネックを調査したところ、checkstyle-validationの実行に1分15秒かかっていることを確認しました。checkstyle-validationのチェックはコンテナ起動時には必要ない処理です。そのため、checkstyle-validationをスキップすることを目指しました。
先ほど同様に事前にcheckstyle-validationを行うことで処理をスキップすることができるかなと思い、いろいろ試したのですがうまくいきませんでした。そこで、pom.xmlで定義しているmavenのcheckstyle pluginの記述を削除するスクリプトをコンテナ起動時(spring-boot run実行前)に実行するように修正しました。その後、コンテナを起動したところ、全体としては20秒まで縮めることに成功したことを確認しました。その後、全体的にログを確認し、特別目立ったボトルネックはなかったため、終了としました。
本タスクを取り組んだ感想
本タスクを取り組んだことで、検証作業の効率化、オートスケーリングの改善、ダウンタイム低減による可用性の向上、デプロイ作業の高速化など、かなり貢献ができたかなと思います。また、buildpack化ができないという点に関しては、ライブラリの選定や技術選定などをより慎重に行うことの大切さを学びました。
終わりに
最後まで読んでいただき、ありがとうございます!