概要
Dockerについて知見が溜まってきたので雑に書き書き
Dockerとは
Linuxカーネルの技術を使ってコンテナという仮想化の1手法を実現するための技術。
仮想化の領域
コンテナはカーネルの機能によって仮想化されます。
VMはハードウェアのような低いレイヤーから仮想化が行われます。
誤解を恐れずに言うと、コンテナが仮想化するターゲットはプロセスで、VMが仮想化したいターゲットはOSです。
「1コンテナ1プロセス」
基本的に「1コンテナ1プロセス」でDockerは動かします。
Dockerは1コマンドの実行をするための技術で、コンテナのライフサイクルはコマンドが実行されている期間だけです。
例えば以下のコマンドはだいたい5秒間実行され、その後ライフタイムを終了します。
$ docker run ubuntu sleep 5
このようにコンテナは指定したコマンドが実行されている1コマンドだけが実行されるような設計になっています。
ステートを持たない
コンテナはImmutableInfrastructureのためのアプローチです。 Immutablにするためにステートを持つのはやめましょう。
どうしても必要な場合はクラウドのマネージドサービスを使うことで事足りることが大半でしょう。
例えばS3やRDSなどなど。
SIGNALを処理する
SIGTERMを意識しましょう。
コンテナは短いライフサイクルで生き死にを繰り返します。
生きるときは楽なのですが、死ぬときが問題です。グレースフルなシャットダウンを行えるようにSIGTERMの処理をしっかり記述しましょう。
ログをstdout/stderrへ吐き出す
ログはstdout/stderrへ吐き出すとファイルという"ステータス"にならず、ローテートなど考えなくて楽です。
なおかつ、JSON形式になっているとあとあと取り回しやすいでしょう。
個人的にフレームワークによってログのスキーマは変わるので、フレームワークのスキーマに則って、JSONで吐き出せば良いと思っています。
コンテナイメージは小さくする
スケールアウトやCIの速度に有利です。
小さければ小さいほど良いですが、過度に小さくするとその後の運用コストに見合ってくるのかは考えましょう。
例えばチームのレベル感に応じてDockerの中にXdebugを入れるのを許容するなど。
サイドカー
コンテナは1台だけたてることも可能ですが、メインとなるコンテナのサブとしてコンテナを起動する事が可能です。
例えば、Golangが動いているコンテナの横で、そのGolangコンテナのメトリクスを取得するためのDatadogを置くようなパターンです。
コンテナは複数協調して動くということを意識しましょう。
Multi-Stage Buildを安易に使わない
マルチステージビルドは大変よいものです。
が、すぐに難読化に繋がります。
使用するとしてもなるべくステージ数を減らすようにしましょう
キャッシュを利用する
Dockerfilerのビルド時にキャッシュを意識した書き方にしましょう。
セキュリティ
- rootは使わない
- 野良のDockerイメージをベースイメージにしない
- ビルド時に機微情報を与えない
- docker.sockをマウントしない
- .dockerignoreを使う
その他
ハンズオン資料です。