この記事の内容
実際に
コンテナイメージを 安全に 保つ 3つの ステップ
Dockerと 共同で 作成した コンテナセキュリティガイド
Dockerを使ったコンテナイメージのセキュリティ
コンテナイメージの
まず、
コンテナイメージのセキュリティを確保する3つのステップ
先ほど
コンテナイメージ自体と、
その 中の ソフトウェア コンテナ、
ホストOS、 同じ ホスト上の 他の コンテナ間の 相互作用 ホストOS自体
コンテナの
ネットワークと ストレージに 関する 懸念事項 多くの
場合、 Kubernetesクラスターでの 実行時セキュリティ

これらの
安全な
この
1. コードと依存関係を安全に保つ
クラウドネイティブアプリケーションを
幸いなことに、

開発の
2. 信頼できるソースの最小限のベースイメージから始める
イメージを
ベースイメージ
Docker Hubには、
Dockerは

Docker Hubで
Docker Official
例と
覚えやすい
コンテナイメージのpythonと

どちらの
状況をcurl、
コンテナイメージのセキュリティを実践する:ベースイメージの選定例
先ほど
引き続きPythonをpython:3-slim-busterイメージを
まずは
FROM python
WORKDIR /app
COPY hello.py /app
CMD [“python3”, “hello.py”]これ以上(“Hello, World!”)を
次に、
$> docker build -t hello-python .
[+] Building 67.4s (5/5) FINISHED
=> [internal] load build definition from Dockerfile 0.4s => => transferring dockerfile: 36B 0.1s => [internal] load .dockerignore 0.4s => => transferring context: 2B 0.1s => [internal] load metadata for docker.io/library/python:latest 1.6s => FROM [1/1] FROM docker.io/library/python 65.1s
...
=> exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:3a92e9... 0.0s => => naming to docker.io/library/hello-python 0.0s
$> docker run hello-python
Hello, World!
$> docker scan hello-python -f Dockerfile
/ Analyzing docker dependencies for hello-python/Dockerfile
Organization: snyk-pmm Package manager: deb
Target file: Project name: Docker image: Base image:
Dockerfile docker-image|hello-python hello-python
python
Tested 431 dependencies for known issues, found 268 issues. Base Image Vulnerabilities Severity
python:latest 268 6 high, 34 medium, 228 low
Recommendations for base image upgrade:
Alternative image types
Vulnerabilities Severity
75 1 high, 10 medium, 64 low
Base Image
python:3-slim-buster
python:3.9-rc-slim-buster 75 1 high, 10 medium, 64 lowまず、pythonイメージに
出力のpython:3-slim-busterイメージです。
DockerfileではFROM行をDockerfile.slimと
FROM python
WORKDIR /app
COPY hello.py /app
CMD [“python3”, “hello.py”]次に、
```
$> docker build -t hello-python:slim . -f Dockerfile.slim
[+] Building 21.0s (8/8) FINISHED
=> [internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Dockerfile.slim 0.1s
=> => transferring dockerfile: 135B 0.0s
=> [internal] load metadata for docker.io/library/python:3-slim-buster 11.5s
...
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:63768699. 0.0s
=> => naming to docker.io/library/hello-python:slim 0.0s
$> docker run hello-python:slim
Hello, World!
$> docker scan hello-python:slim -f Dockerfile.slim
Package manager: deb
Target file: Dockerfile.slim
Project name: docker-image hello-python
Docker image: hello-python:slim
Base image: python:3-slim-buster
Licenses: enabled
Tested 94 dependencies for known issues, found 75 issues.
According to our scan, you are currently using the most secure version of the selected base image
```今回は、
3. ベースイメージとコードの間にあるすべてのレイヤーを管理する
ベースイメージには
幸い、FROM行よりRUN、COPY、ADDコマンドに

これらの
段階ごとに
コンテナの脆弱性修正に優先順位を付ける
とはいえ、セキュリティ脆弱性は
まずは、
開発用イメージから
始める
開発用イメージは、ツールや サポートパッケージを 最も 多く 必要と する ため、 中間レイヤーに 含まれる 脆弱性が 最も 多くなる 傾向が あります。 ただし、 段階的に イメージを ビルドし、 本番用イメージに これらの 追加要素を 含めないのであれば、 この 段階の 脆弱性の 多くは 無視しても 問題ない 可能性が あります。 その 判断には、 コンテナに インストールされた 依存関係を 追跡し、 開発の イナーループに 何が 必要かと いう 知識と 照らし合わせる 必要が あります。 ある ライブラリが、 別の 依存関係の さらに 依存関係と して インストールされ、 その 先の 依存関係に 脆弱性が 含まれている ことは 珍しく ありません。 開発用パッケージを 1つ 削除するだけで 脆弱性を 解消できるかどうかを 判断できる 必要が あります。 次の
例では Rubyアプリケーションを 使っています。 開発を 簡単に する ため、 Rubyに SQLiteを バンドルするのは 一般的ですが、 本番環境では 同じ SQLiteデータベースを 使わないでしょう。 この 点を 把握し、 コンテナの 脆弱性スキャンで 適切な 情報を 得られれば、 開発環境で SQLiteとともに インストールされる ライブラリの 脆弱性は 無視する、と 判断できます。 Dockerスキャンで こうした 情報や、 作業を 大幅に 簡単に する 追加情報を どのように 得られるかを 見ていきましょう。 
テスト用イメージを
整理する
テスト用イメージ:脆弱性への対処方法と いう 点では、 実際の ところ 開発用イメージと 大きな 違いは ありません。 本番用イメージに 含まれない テスト用パッケージに 脆弱性が あると わかっていれば、 無視しても よいでしょう。 この 段階では、 特に 開発段階で 重大な 脆弱性を 無視する ことにした 場合、 開発段階の スキャン結果と 比較するのが おすすめです。 開発用イメージに あった 脆弱性は、 テスト用イメージで 本当に 解消されていますか? 解消されているなら、 プロセスは 機能しています。 そうでなければ、 開発用イメージまたは ビルド手順を 見直す 必要が あるかもしれません。 本番用イメージを
しっかり 固める
本番用イメージ:は、実際に どこかで 実行され、 外部に 公開される 可能性も ある ため、 特に 重要です。 それでも、 可能な 限りイメージを 軽量化して 不要な ものを 削除したとしても、 脆弱性ゼロの 実現は 困難でしょう。 多くの 場合、 目標は リリースプロセスの 自動化です。 高リスクの 脆弱性、 特に 既知の エクスプロイトが ある ものには 必ず 対処しましょう。 また、 開発段階や テスト段階の イメージも スキャンする 理由の 1つは、 リリース直前に 予期せぬ 問題が 発生するのを 減らす ことです。 早い 段階で リスクを 軽減できていれば、 本番環境の スキャンは 主に、 直前に 発見された 新たな 脆弱性を 見つける ための ものとなります。
別の
実践例:ユーザーが追加した脆弱性の修正を優先する
この
こちらがDockerfileです。
```
FROM ruby:2.5.1
RUN apt-get update && \
apt-get install -y git vim && \
rm -rf/var/lib/apt/lists/*
RUN gem update --system 3.0.4 && \
gem install bundler -V '2.0.2'
WORKDIR /usr/src/app/alpha-blog
COPY . .
ENV BUNDLER VERSION 2.0.2
RUN bundle update && \
bundle install && \
rails db:setup && \
rails db:migrate
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
```Rubyの
最初の
RUN行では、イメージ内で ローカル開発を 行う ための ユーティリティを いくつか 追加します。 続いて、
Rubyの 主要コンポーネントを 更新し、 使える 状態に します。 COPY . .コマンドでコードを コピーします。 RUN bundle…コマンドでRailsプロジェクトを セットアップします。
「イメージに
何が
前と
```
$> docker build -t blog .
[+] Building 111.5s (11/11) FINISHED
.
.
.
=> [6/6] RUN bundle update && bundle install &&
rails db:setup && rails db:migrate 108.8s
=> exporting to image 1.6s
=> => exporting layers 1.6s
=> => writing image sha256:0b7c017032e301429...433c23a5 0.0s
=> => naming to docker.io/library/blog 0.0s
$> docker scan blog -f Dockerfile
Testing blog...
.
.
.
X High severity vulnerability found in bzip2
Description: Out-of-bounds Write
Info: https://snyk.io/vuln/SNYK-DEBIAN9-BZIP2-450801
Introduced through: bzip2@1.0.6-8.1, bzip2/libbz2-dev@1.0.6-8.l, imagemagick/libmagickcore-dev@8:6.9.7.4+dfsg-11+deb9u6,meta-common-packages@meta
From: bzip2@1.0.6-8.1
From: bzip2/libbz2-dev@1.0.6-8.1
From: imagemagick/libmagickcore-dev@8:6.9.7.4+dfsg-ll+deb9u6>imagemagick/libmagickcore-6.q16-dev@8:6.9.7.4+dfsg-1l+deb9u6 › bzip2/libbz2-devel.0.6-8.1
and 1 more..
Introduced by your base image (ruby:2.5.1)
X High severity vulnerability found in apt/libapt-pkg5.0
Description: Arbitrary Code Injection
Info: https://snyk.io/vuln/SNYK-DEBIAN9-APT-407402
Introduced through: apt/libapt-pkg5.0@1.4.8, apt@l.4.8
From: apt/libapt-pkg5.001.4.8
From: apt@l.4.8 > apt/libapt-pkg5.001.4.8
From: apt@l.4.8
Introduced by your base image (ruby:2.5.1)
Fixed in: 1.4.9
Organization: snyk-pmm
Package manager: deb
Target file: Dockerfile
Project name: docker-image|blog
Docker image: blog
Base image: ruby:2.5.1
Licenses: enabled
Tested 413 dependencies for known issues, found 871 issues.
Base Image Vulnerabilities Severity
ruby:2.5.1 867 48 high, 237 medium, 582 low
Recommendations for base image upgrade:
Minor upgrades
Base Image Vulnerabilities Severity
ruby:2.5 257 6 high, 34 medium, 217 low
Alternative image types
Base Image Vulnerabilities Severity
ruby:2.5-slim 53 0 high, 5 medium, 48 low
ruby:2.7.0-slim-buster 61 1 high, 8 medium, 52 low
ruby:2.7.0-preview3-slim-buster 63 1 high, 9 medium, 53 low
ruby:2.7.0-preview2-slim 63 1 high, 9 medium, 53 lowこの
docker scanコマンドで–exclude-baseオプションを
—exclude-baseオプションを-f Dockerfileオプションを
X High severity vulnerability found in curl/libcurl3
Description: Buffer Overflow
Info: https://snyk.io/vuln/SNYK-DEBIAN9-CURL-466505
Introduced through: curl@7.52.1-5+deb9u7, curl/libcurl4-openssl-dev@7.52.1-5+deb9u7, gitel:2.11.0-3+deb9u7
From: curl@7.52.1-5+deb9u7 > curl/libcurl3@7.52.1-5+deb9u7
From: curl/libcurl4-openssl-dev@7.52.1-5+deb9u7 › curl/libcurl3@7.52.1-5+deb9u7
From: curl@7.52.1-5+deb9u7
and 2 more..
Introduced in your Dockerfile by `RUN apt-get update && apt-get install -y git vim && rm -rf/var/lib/apt/lists/*`
Fixed in: 7.52.1-5+deb9u10
Organization: snyk-pmm
Package manager: deb
Target file: Dockerfile
Project name: docker-image|blog
Docker image: blog
Base image: ruby:2.5.1
Licenses: enabled
Tested 413 dependencies for known issues, found 70 issues.これなら、Introduced in your Dockerfile by」で
それでも、
セキュリティチームと
JSON出力オプションと、jqをjqは
```
$> docker scan blog -f Dockerfile --exclude-base --json | \
jq '[.vulnerabilities[]
| select(.nearestFixedInVersion)
| select(.severity == "high")
| { packageName,
dockerfileInstruction,
title,
severity,
version,
nearestFixedInVersion}]'
$> docker scan blog -f Dockerfile --exclude-base --json | \
jq '[.vulnerabilities[]
| select(.nearestFixedInVersion)
| select(.severity == "high")
| { packageName,
dockerfileInstruction,
title,
severity,
version,
nearestFixedInVersion}]'
[
{
"packageName": "curl",
"dockerfileInstruction": "apt-get install -y git vim",
"title": "Out-of-bounds Write",
"severity": "high",
"version": "7.52.1-5+deb9u7",
"nearestFixedInVersion": "7.52.1-5+deb9u13"
},
...
{
"packageName": "perl",
"dockerfileInstruction": "apt-get install -y git vim",
"title": "Integer Overflow or Wraparound",
"severity": "high",
"version": "5.24.1-3+deb9u4",
"nearestFixedInVersion": "5.24.1-3+deb9u7"
},
{
"packageName": "perl",
"dockerfileInstruction": "apt-get install -y git vim",
"title": "Buffer Overflow",
"severity": "high",
"version": "5.24.1-3+deb9u4",
"nearestFixedInVersion": "5.24.1-3+deb9u7"
},
{
"packageName": "perl",
"dockerfileInstruction": "apt-get install -y git vim",
"title": "Out-of-bounds Write",
"severity": "high",
"version": "5.24.1-3+deb9u4",
"nearestFixedInVersion": "5.24.1-3+deb9u7"
}
]
```これでjqコマンドにjqは
まず、--json出力オプションをjqを
出力から
脆弱性だけを 選択 修正可能な
脆弱性と、 深刻度が 「high」の 脆弱性だけを 選択 脆弱性に
関する 一部の フィールドだけを 表示し、 出力を 整理
まとめ
コンテナセキュリティは
信頼できる
プロバイダーのベースイメージから 始めましょう。 デジタル署名を 使って 真正性を 確認してください。 可能な
場合は、 基本的な OSパッケージと 選択した フレームワークの バージョンだけを 含む最小限の ベースイメージを 選び、 そこから 必要な ものを 追加しましょう。 イメージは
早い 段階から、 定期的に 脆弱性を スキャンしましょう。 積極的に メンテナンスされ、 すべての セキュリティチェックに 合格した 承認済みの ベースイメージを 用意し、 新しい イメージを 作成する たびに 再度スキャンしてください。 ソフトウェアライフサイクルの
複数の 段階でスキャンを 実施しましょう。 デスクトップ、 CI、 レジストリに 保存された イメージ、 クラスターで 実行中の コンテナや Podが 対象です。 スキャンツールを
選ぶ ときは、表示される 脆弱性の 一覧だけで 判断しないでください。 脆弱性を
報告するだけでなく、 より 新しい、または より 適切な ベースイメージが ある ことも通知してくれますか? 脆弱性の
検出に よって ビルドが 失敗した 場合、 開発者や DevOpsチームが 問題を 修正できるだけの 情報を 提供しますか? 必要な
セキュリティゲートを 柔軟に 設定できますか? すべてに
通用する 方法は ありません。 開発者は、 本番環境では 許可できない ツールを イメージに 追加する 必要が ある ため、 開発ライフサイクルの 各段階で 異なる イメージを 使う こともあります。 こうした 段階を サポートする 自動化、 CI、 Dockerfileを 活用すれば、 適切な セキュリティゲートを 設け、 セキュリティと 生産性の バランスを 適切に 保てます。
Dockerと