インフラ

Chainguardイメージとよく使用されるDockerイメージとの違い

Chainguardの画像

reisuta

Webエンジニア | 20代中盤 | 大学時代はGmailすら知らないIT音痴でプログラミングとは無縁の生活を送る → 独学でプログラミングを学ぶ → Web系受託開発企業にエンジニアとして就職 → Web系自社サービス企業に転職 | 実務未経験の頃からVimを愛好しており、仕事でもプライベートでも開発はVimとTmuxを使っているので、VSCodeに疎いのが最近の悩み。何だかんだでやっぱりRubyが好き。

Dockerのイメージの中で、
サイズが小さくてセキュリティが高い印象を受ける有名どころとしては、
Alpineなどがあるかと思いますが、
もっとこれらに特化したイメージがあります。

それが本記事で取り上げるChainguardです。

もしかすると、そこまで知名度があるわけではないかもしれませんが、
イメージサイズとCVEの少なさは随一です。
高度のセキュリティを誇ることが、Chainguardの特徴です。

本記事では、そんなChainguardとは何か?から、
実際に一般的なDockerイメージと比べた特徴を、
脆弱性スキャンを行いつつハンズオンします。

日常的にDockerを使用していて、
より良いDockerイメージを模索している人にとって、
参考になれば幸いです。

そもそもDockerがよくわからんっていう人は、
下記の記事と動画で詳細に解説しているので、
そちらを先にご覧になってからのほうが、
本記事の理解がスムーズかもしれません。

Chainguardとは何か?概要解説

Chainguard(イメージ)は、Chainguard社によって提供されている、
高いセキュリティを誇るコンテナイメージ群です。

dockerhubでChainguardと検索すると、
500以上のイメージがヒットすることがわかります。

https://hub.docker.com/search?q=Chainguard

Chainguardの特徴は、やはり従来のコンテナイメージの構築と運用に伴う
セキュリティリスクを軽減していることでしょう。

下記が公式のページです。

https://www.chainguard.dev

0 CVE containerと打ち出していることからも分かる通り、
セキュリティやコンテナイメージサイズの縮小などに強みを持った、
イメージであることがわかります。

ちなみに、CVEというのは、
Common Vulnerabilities and Exposures の略称で、共通脆弱性識別子と言ったりする、
要するに脆弱性のリストのようなものかと思います。

https://www.sompocybersecurity.com/column/glossary/cve
https://www.redhat.com/ja/topics/security/what-is-cve

そんな脆弱性のリストが0ということからも分かる通り、
Chainguardが一般的なDockerイメージと比べて高いセキュリティを誇っていることが伺えます。

Chainguardのセキュリティ

すでに述べたようにChainguardの大きな魅力は、
そのセキュリティ機能です。

その中でも、Chainguardイメージは、
Wolfiというアンディストリビューション(undistro)なOSをベースとしていることが
大きな特徴でしょう。

https://edu.chainguard.dev/open-source/wolfi/overview

また、distrolessなイメージとして、
不要なソフトウェアが入っていないことも特徴です。

https://edu.chainguard.dev/chainguard/chainguard-images/getting-started-distroless

Alpineとかを使ったことがある方は、
コンテナサイズが小さい分、何も入っていないから、
自分で結構色々インストールしなきゃいけなかったみたいない印象があるかもしれません。
ChainguardイメージはそんなAlpineよりもさらに無駄が削ぎ落とされています。

というのも、Chainguardは、下記のような特徴をもっています。
(※公式のやつを訳して貼ってあるだけなので、公式の方を見てもらったほうがいいかもです)

ポイント

・不要なソフトウェアを排除したミニマルなデザイン
・自動化ビルドにより、イメージの最新性と利用可能なセキュリティパッチを確保していること
・イメージ内のすべてのアーティファクトの出所を証明する高品質のビルドタイム SBOM (ソフトウェア部品表)
・Sigstore によって提供される検証可能な署名
・Cosign と apko による再現可能なビルド

とまあ、基本的にはもともと不要なソフトウェアを排除したミニマルデザインなのに、
その中でも使われている技術の信頼性は担保しているという、
本当にセキュリティに特化しているなという印象を受けました。

こうした特徴から、Chainguardはセキュリティに特化していることはもちろん、
コンテナサイズの縮小にも寄与したコンテナプラットフォームとして、非常に魅力的だと考えます。

よく使用されるDockerイメージと何が違うのか?

さて、そんなChainguardですが、
よく使用されるDockerイメージと何がどれぐらい違うのでしょう。

なんとなくセキュリティがすごそうということはわかりましたが、
まだいまいちイメージがわかないかと思うので、
ここでRubyのChainguardイメージ、RubyのAlpineイメージ、一般的なRubyのDockerイメージの
3つのコンテナを立ててみようと思います。

Rubyの一般的なDockerイメージの環境構築

まずは、普通のDockerイメージの方を環境構築します。
簡易的なもの(というか脆弱性スキャンがメイン)なので、
今回はsinatraを使おうと思います。

まずは起動するapp.rbを作成します

require 'sinatra'

set :bind, '0.0.0.0'

get '/' do
  'Hello, from Docker!'
end

次にGemfileを作成します。
sinatraだけだとエラーになるので、rackupも追加します

source 'https://rubygems.org'
gem 'sinatra'
gem 'rackup'

次にDockerfile.rubyを作成します

FROM ruby:latest

WORKDIR /app

COPY Gemfile ./
RUN bundle install

COPY . .

CMD ["ruby", "app.rb"]

まあよくあるDockerファイルの記法という感じですね。

あとは、buildとrunをします。

docker build -t ruby-demo -f Dockerfile.ruby .
docker run -d -p 5000:4567 --name ruby-demo-container ruby-demo

docker ps を行って、問題なくコンテナが立ち上げっていればOKです

RubyのChainguardイメージの環境構築

次にChainguardの方も環境構築します。

Gemfileとapp.rbは共通なので、
Dockerfile.chainguardだけ作成します

FROM cgr.dev/chainguard/ruby:latest-dev as builder

ENV GEM_HOME=/work/vendor
ENV GEM_PATH=${GEM_PATH}:/work/vendor

COPY Gemfile /work/
RUN gem install bundler && bundle install

FROM cgr.dev/chainguard/ruby:latest

ENV GEM_HOME=/work/vendor
ENV GEM_PATH=${GEM_PATH}:/work/vendor

COPY --from=builder /work/ /work/
COPY app.rb /work/

ENTRYPOINT [ "ruby", "app.rb" ]

さて、Chainguardの方ですが、
こちらは少し書き方がトリッキーになります。
普通のRubyイメージの書き方と同じようにすると、
画像のようにshがない的なエラーになって
bundle installとかができません。

これは最初にちらっと触れましたが、
distrolessなイメージとして
シェルとかパッケージマネージャーも省かれているので、
まあ当然といえば当然ですね。

なのでFROMでは、cgr.dev/chainguard/ruby:latest ではなくて、
cgr.dev/chainguard/ruby:latest-dev を指定します。

ただ、これだけでもダメで、
今度はrubyコマンドがない的なエラーにも遭遇するので、
multi stage build構成にします。

この辺の詳細はこのあたりに書かれています。

https://edu.chainguard.dev/chainguard/chainguard-images/getting-started/ruby

書きなれたDockerfileの記法とは少し異なる書き方が必要なので、
このあたりは慣れが必要かもしれません。

docker build -t chainguard-ruby-demo -f Dockerfile.chainguard .
docker run -d -p 5001:4567 --name chainguard-ruby-demo-container chainguard-ruby-demo

さて、docker ps で無事立ち上がればOKです

RubyのAlpineイメージの環境構築

さて、3つ目にAlpineの方も行おうと思います。

Gemfileとかapp.rbは同じく共通なので、
Dockerfile.alpineをまず作成します

FROM ruby:alpine

WORKDIR /app

COPY Gemfile ./
RUN bundle install

COPY . .

CMD ["ruby", "app.rb"]

alpineの場合、何か別途インストールしないとダメかなと思いましたが、
意外にも普通のRubyイメージと同じ構成のDockerfileで問題なく立ち上がりました。

docker build -t ruby-demo-alpine -f Dockerfile.alpine .
docker run -d -p 4567:4567 --name ruby-demo-alpine-container ruby-demo-alpine

何も入っていないように思えたAlpineも、
比べてみるとまだ色々入っている方なのかもしれないと感じる瞬間でした

各イメージの脆弱性スキャン

さて、各イメージの環境構築をしたので、
脆弱性スキャンやイメージサイズを比較してみます。

まず、イメージのサイズを比較してみます。

docker images | grep demo

一般的なRubyイメージが以下に巨大かが伺えますね。
alpineも結構小さいですが、Chainguardはそれを更に上回ってサイズが小さいですね。

trivyを使った脆弱性スキャン

次に、trivyを使用して、イメージのセキュリティスキャンも実行してみます
trivyがなければ、homebrewとかでインストールしておきます。

https://github.com/aquasecurity/trivy

brew install trivy

trivy image ruby-demo
trivy image chainguard-ruby-demo

chainguard-ruby-demoが圧倒的に脆弱性が少ないことが伺えます

grypeを使った脆弱性スキャン

grypeの方でも、脆弱性スキャンを行ってみようと思います。

https://github.com/anchore/grype

まずは公式に従ってcurlでインストールしときます

curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin

とやってみたが、
curlだと上手いことインストールできなかったので、
homebrewでインストールしました。

brew tap anchore/grype
brew install grype

インストールしたら、早速スキャンしてみます。

grype ruby-demo
grype ruby-demo-alpine
grype chainguard-ruby-demo

ruby-demoの方は、
CVEがたくさん出てきましたが、
chainguard-ruby-demoの方は、
なんと驚きのNo vulnerabilities found でした。
(alpineもmediumが1つだけだったのでかなり少ない...!)

すごい!!

ていうか、これをやるまで
知りませんでした、普通のRubyイメージの方は、
gitとかpython3まで入っているんですね...
(このgitに脆弱性があるようでしたが)

Docker Scoutでの比較

もうtrivyやgrypeを使って比較したので、
結果は見えていますが、
最後にdockerhubのScoutを使って見ようと思います。

まずは、dockerhubのアカウントを作成して、
cliでログインします。

docker login

次に、それぞれのイメージをタグ付けし、
pushします。

docker tag ruby-demo <your-dockerhub-username>/ruby-demo
docker tag ruby-demo-alpine <your-dockerhub-username>/ruby-demo-alpine
docker tag chainguard-ruby-demo <your-dockerhub-username>/chainguard-ruby-demo

docker push <your-dockerhub-username>/ruby-demo
docker push <your-dockerhub-username>/ruby-demo-alpine
docker push <your-dockerhub-username>/chainguard-ruby-demo

pushしたら、docker-hubにアクセスします

https://hub.docker.com

chainguardの脆弱性は0でした。

alpineでも5つぐらいありますね。
普通のRubyイメージは115個...

Dockerイメージと比べたChainguardの魅力

本記事では、有名どころのDockerイメージと
Chainguardイメージを主にイメージサイズと脆弱性の観点で
比較してみました。

Chainguardイメージは、やはりその高いセキュリティと
極限にまで縮小されたイメージサイズが特徴であり、
それらが大きな魅力だと私は感じました。

何気なく使っている、Dockerの普通のイメージとかが、
以下に肥大化したソフトウェアを内包していて、
多くの脆弱性を抱えているかが本記事で明らかになったかと思います。

Chainguardは、日本語での情報がまだ多くはなく、
通常のDockerfileに比べ、ややトリッキーな記法や、
Wolfi OSやdistroless、undistroといった、
人によっては馴染みが薄い概念も多くあるので、
技術的キャッチアップコストは、通常のDockerイメージよりは大きくなるかもしれませんが、
それを払ってでも、積極的に採用したい魅力的なDockerイメージだと思います。

本記事が、より良いDockerイメージの技術選定の参考になれば幸いです。

  • この記事を書いた人
  • 最新記事

reisuta

Webエンジニア | 20代中盤 | 大学時代はGmailすら知らないIT音痴でプログラミングとは無縁の生活を送る → 独学でプログラミングを学ぶ → Web系受託開発企業にエンジニアとして就職 → Web系自社サービス企業に転職 | 実務未経験の頃からVimを愛好しており、仕事でもプライベートでも開発はVimとTmuxを使っているので、VSCodeに疎いのが最近の悩み。何だかんだでやっぱりRubyが好き。

おすすめ記事はこちら

Vim/Neovimプラグイン 1

プラグインをどれだけ入れるかは、その人の思想なども関係するので、一概にこれがいいというのはないかもしれません。 プラグインを全く入れない人もいれば、100個以上入れる人もいます。 ただそれでも、これだ ...

VimとNeovimの比較 2

本記事では、VimとNeovimの違いについて、解説します。 VimとNeovimの違いについては、普段頻繁にVimなどを使う方でなければ、正直、あまり気にしなくてもいいかなと思います。 ただ、Vim ...

Ruby変数やすべてがオブジェクトについて 3

本記事は、Rubyの基礎文法である、変数や真偽値、論理演算子に触れると同時に、「すべてがオブジェクト」というRubyの特徴的な思想についても解説します。 この思想は、Rubyの文法の根幹になっているの ...

4

エンジニアにおすすめの技術書 書籍学習は、エンジニアの嗜みみたいなところがありますが、 良書というものは、意外とそこまで多くもありません。 そこで本記事では「技術書マニアの筆者が厳選した技術書20選」 ...

5

エンジニアになるには? プログラミングは、専門性が高く自分一人で勉強するのが大変に感じることも多いですよね。 そこで本記事では「おすすめのプログラミングスクール5選」を特徴と、現役エンジニア目線で優れ ...

-インフラ