本記事
以下のようになんとなくコンテナイメージを使っていませんか。
FROM golang:1.9 ...
しかし、これはセキュリティ的に脆弱性をアプリケーションに持ち込むだけでなく。Google Cloud Registryを使っているならコストがより多くかかるなどいいことがないので、今回はベストプラクティスとしてDockerコンテナイメージの作り方を紹介しようと思います。
目次
Building Small Containers
コンテナのボリュームの違い
たとえばGolangだと以下のようなtagで用意されています。
実際に1.11
と1.11-strech
と1.11-apline
をpullしてみます。
確認すると以下のようになっています。
REPOSITORY TAG IMAGE ID CREATED SIZE golang 1.11-alpine 95ec94706ff6 12 hours ago 310MB golang 1.11 be13d0c67b75 12 hours ago 777MB golang 1.11-stretch be13d0c67b75 12 hours ago 777MB
このように同じバージョンでもコンテナサイズが異なることがわかります。
セキュリティの脆弱性
デフォルトのgolang:1.11
やこれにポインタをもつgolang:latest
は大きな容量です。
アプリケーションの大きなはせいぜい数MBですから、セキュリティの脆弱性やバグが紛れ込みやすくなります。
小さなイメージにする方法
以下の二つの方法でイメージの小型化します。
1. 小さなイメージを使う方法
例えばNode.jsだとさらに顕著になります。
しかし、コードを入れて、依存環境をインストールしなければならないですが、あまり難しい作業ではありません。
2. Builderパターンを使う
コンパイル型言語では、コンパイル済みコードに変換されます。
コンテナ内でコンパイルするとコンパイラなど余分なものがあります。
以下のようなBuilderパターンと呼ばれるようなパターンを使って小型化をすることができます。
2.1 ビルドコンテナ
まず、ビルドコンテナを用意します。
ここではユニットテスト、コンパイラ、開発のための依存関係のためのツールを持ちます。
コンパイルしたものをランタイムコンテナに格納します。
まず、以下のようなコンテナをつくります。
2.2 ランタイムコンテナ
実際にプロダクションで使われるコンテナのことです。
コンパイル済みのコンテナしかありません。
2.3 実際のDockerfile
以下のようなアプリケーションを書いているかもしれません。
FROM golang:1.8-apline LABEL MAINTAINER=KeisukeYamashita WORKDIR /app ADD . ./app RUN cd /app && go build -o goapp EXPOSE 8080 CMD ["./goapp"]
これをBuilderパターンに合致させます。
FROM golang:1.8-apline AS build-env LABEL MAINTAINER=KeisukeYamashita WORKDIR /app ADD . ./app RUN cd /app && go build -o goapp FROM alpine RUN apk update && apk add ca - WORKDIR /app COPY --from=build-env /app/goapp /app EXPOSE 8080 ENTRYPOINT ./goapp
二つ目のFROM
はlinuxはapline
であります。
これによって最後のFROM
で構成されているコンテナで構築することもできます。
Small Imageの恩恵
1. パフォーマンス
以下の項目でパフォーマンスの向上が見られた。
例: 項目: B:Big Imageでの値 S: Small Imageでの値
- ビルド時間: B: 54s S: 28s
- Push時間: B: 48s S: 16s
- Pull時間: B:52s S: 6s
これによってGoogle Cloud EngineやKubernetesのデプロイメントタイムを大幅に向上することができる。
2. セキュリティ
一般的には小さいイメージの方が脆弱性は低いことが知られている。
Google Cloud Registryでは自動的にコンテナの脆弱性をスキャンしてくれる。
3. コスト
3.1 Cloud Container Registry
以下が公式ページです。
Container Registry の料金 | Container Registry | Google Cloud
システムによって Cloud Storage バケットが作成され、すべてのイメージが保存されます。このストレージに対して料金が課金されます。
また、Container Registry ストレージ バケットに使用されるデフォルトの Cloud Storage クラスは、Multi-Regional であり、Multi-Regional バケットの月額料金は、約 $0.026/GB です。
容量が小さければ小さいほどStorageコストが抑えられることがわかります。
3.2 Cloud Builder
2節でビルド時間が大幅に小さくなることがわかりました。
1日あたり120分のビルドまでは無料です。
しかし、それを超過するとビルド時間に対して$0.0034/ビルド分だけお金がかかってしまいます。
この様にビルド時間を削減できると、コストを抑えられることができます。
まとめ
Small Imageにするしかないし、今までしてこなかった自分に反省です。