コンテナに積み込もう

この記事はコンテナに乗り遅れた人達へで話したコンテナ化する際に考える事をまとめたものです。

レガシーでモノリシックなアプリ開発運用をターゲットにしてますがどこでも使えるかと思います。

今回の動機

コンテナって世の中的にはもうやってるとこも多いけど、まだまだ乗り切れてない人もいるかと思います。そんな人たちにはまず何から始めれば良いのか、何を考えないといけないのか、もうやってる人はわかると思うけどまだ触ってない人には何すれば良いかわからなくて恐ろしくハードルが高いように見えるんじゃないかなと思います。今回はそのためのガイドになったら良いなー、ということでやってみました。

なぜやるのか

そもそもなんでコンテナ化する必要があるんだっけ?と言うところから。やるならそれなりに時間取って動作確認もしないといけないのでわりと大変な労力です。

  • イミュータブルである
  • どこでも動く、同じものが動く
  • 余計なものが動かない
  • スケールしやすくなる
  • 環境構築=Dockeifile
  • 開発言語に関係なく運用時のインタフェースを共通に出来る
  • 組織が変わる

コンテナはイミュータブルです。これの何が良いかというと仮に環境がぶっ壊れてもコンテナ立ち上げ直せば元通りです。実行環境がぶっ壊れても新しくコンテナが動く環境さえ出来れば同じコンテナ持ってきてすぐ動かせます。つまりスケールアウトも容易なわけです。

アプリに必要な依存関係のみを内包しかつアプリ以外のプロセスは動かないので軽量です。長く運用しているうちに知らん間に依存関係が増えてて再構築時に困るとかあるあるかなと思います。Dockeifileで構築することでこれを常に意識させてくれます。

開発言語がなんであってもアプリ固有の起動方法とかがあると運用時にコンテキストスイッチが発生してヒューマンエラーも起きやすくなりますよね。そこら辺を共通の言語としてコンテナにすることで運用の負荷を減らすことが出来ます。開発と運用のやるべき境界が変わるんです。開発がDockeifile書いて環境構築するところまで責任を持ちます。一見開発でやることが増えたようにも見えますけど、ローカルだったりテスト環境で開発の人環境作りますよね。なのであんま変わんないかと(違う場合もあるかもしれないけどごめんね)。

開発が自立して環境構築出来るようになると運用も運用のことに専念できるしいいんじゃない?という感じでしょうかね。

最初に考えること

一番大事なことはアプリケーションのことを知る事です。

ここ超大事。当たり前じゃんと思うかもしれないけど、ミュータブルな環境だと知らない間になんか動くようになってていざ新しく作ろうとすると動かないなんて事もよくあるわけです。アプリがよく出来てればそんなこともないかもしれないけど、大体レガシーなアプリはそんなことないです。考えることとしては大体以下のような感じです。

  • アプリの種類は?
  • アプリの I/O は?
  • 動作に必要な依存関係は?
  • 関連のプロセスは?

アプリの種類についてはバッチかコマンドなのかウェブアプリとかなのか、てとこです。ポートは何かリッスンするようなものならポートは?とかそゆとこ。バッチなら後の I/Oは超重要ですね。コマンドならどこかに命令するだけなのかファイル出力するのかとかで変わってきます。

次が一番重要なI/Oを把握することです。ログはどっか出してるのか?DBへの書き込みはあるか?どういうインプットがあるか?とか。

依存関係を把握するの超大事です。まずはこれまでの構築手順書的なものを見ていきましょう。そしてアプリを動かすのに必要な構築手順を把握します。とりあえず今書いてあるのと動いてる環境が正だと思うのでまずはそれに従います。

関連するプロセスがあるならこれも別途コンテナ化します。難しそうなら別途考える必要があるかも。

やってみる

大きく実際やることとしては以下かなと。

  • ログの見直し
  • アプリケーションの見直し
  • Dockerfile書く
  • CI/CD ジョブの見直し

ログの見直し

ログはこれまでだとログを用途別にファイル別々に出力してってことをしてたかと思いますが、ログは全て標準出力に吐きましょう。とは言うものの、これはログの基盤がしっかりしていないとなかなか難しいと思います。ログを Stackdriver, BigQuery などで見れるようにしてからでもいいかと思います。

最初は今までどおり同じパスにログ出力しちゃいましょう。ログ出力するパスはボリュームをマウントして永続化します。

焦らず追々やっていけばいいです。

アプリケーションの見直し

これも最初はやらなくてもいいし、最終的にも場合によってはやらなくてもいいです。

モノリシックなアプリであればコンテナイメージが大きくなるかと思いますがまずはコンテナ化しましょう。

あとから長期的なロードマップとしてマイクロサービス化していくような方向もありだと思います。

短期的にはアプリケーションの設定ファイルをどうするかとかそういうところだけ気にしとけばいいです。

Dockerfile書く

Dockerfileはコンテナイメージ作成の設計書です。大きく以下になるかな、と。

  • ベースイメージの選定
  • ランタイムのインストール方法
  • アプリケーション配置
  • 設定ファイル

まずはベースイメージの選定ですが、小さいイメージほどいいのですが、まずは今動いているOSと同じOSを使いましょう。イメージが大きくなりますがとりあえず動くことを目標にやりましょう。あとからコンテナイメージのダイエットしていけばいいです。

次にランタイムなどの依存関係をインストールしていくのですが、古の手順書を見ながらDockerfileに書いていくしかないです。ここは根性。動かないものがあればググったりして調べます。ここが多分一番トライアンドエラーを繰り返すんじゃないかと思います。

ここまでで一旦できたらそれをアプリケーションのベースイメージとしましょう。あとから作り直すことも可能です。一旦これでいいです。

次にアプリケーションの配置ですが、既存のアプリケーションデプロイ手順をDockerfileに記述していくような感じになるかと思います。実際これいらないでしょ、みたいなものは意訳する必要はあるかと思いますが、ここもがんばっていきましょう。

基本的にはビルド済みのアプリケーションをコンテナに置けばいいはず。まあアプリによっては違うと思うのでそれぞれでがんばってください。

設定ファイルについて、DBの接続情報とか環境依存の設定値がある場合は設定ファイルをホストサーバに置いてそれをマウントする形が一番手っ取り早いかと思います。

ただ、これだと全てのサーバに設定ファイルを置く必要があるので可能だったら差分は最小にした方がいいでしょう。環境変数から読むような作りにできるならそっちの方がいいかもしれません。

CI/CD について

イメージとしては、CIでビルドしてたステップの次のジョブとしてコンテナ化するようなジョブが追加される感じかと。上記で作成したDockerfileを使ってコンテナイメージをビルドします。

最終的にはコンテナのマルチビルドでアプリケーションのビルドもコンテナ化したいですね。

CDでアプリケーションをデリバリするところはコンテナ化した手順に置き換わります。ここは置き換えがんばりましょう。

がんばりましょうとは言え、一回書いちゃえば最初にも書いたとおりほぼ同じインタフェースになるのである程度使い回せるようになると思います。

コンテナ化ロードマップ

ざっくりこんな感じかと。

  1. 最初はありのままをコンテナ化する
  2. 次にログを便利に使えるものを導入してログ出力を一本化する
  3. コンテナイメージダイエット
  4. マイクロサービス化

こんな感じで進んでいければいいかなと思います。

まとめ

たぶん一番労力使うのは現状を把握することでしょう。がんばりましょう。次に労力いるのは最初のイメージ化でしょう。ここも一回頑張って作ってしまえばそこからは変更だけになるのでがんばりましょう。気合です。

コンテナの絵書いたら色のチョイスのせいでカステラみたいになってしまいました。おなかすいてたらごめんなさい。