Dockerfile のベストプラクティス トップ 20

SHARE:

イメージのビルドにDockerfile のベストプラクティスを迅速に適用することで、セキュリティ問題の防止とコンテナ化されたアプリケーションの最適化を行う方法をご紹介します。

コンテナ化されたアプリケーションやマイクロサービスに精通している方は、サービスはマイクロであるものの、脆弱性の検知、セキュリティ問題の調査、およびデプロイ後の報告と修正によって、管理オーバーヘッドがマクロになっていることに気づいているかもしれません。

このオーバーヘッドの多くは、セキュリティをシフト・レフトし、開発ワークフローの中で潜在的な問題をできるだけ早く解決することで回避できます。これについては、イメージスキャンに関するベストプラクティスで紹介しました。


適切に設計された Dockerfile は、特権コンテナの使用や不要なポートの公開、未使用のパッケージ、漏洩した認証情報など、攻撃に利用される可能性のある要素を排除します。こうした既知のリスクを事前に取り除くことで、セキュリティ管理や運用上の負荷を軽減することができます。

使用するツールのベストプラクティス、パターン、および推奨事項に従うことで、よくあるエラーや落とし穴を回避することができます。

この記事では、Dockerfile の作成とコンテナセキュリティに焦点を当てた、厳選されたDocker セキュリティのベストプラクティスのリストについて詳しく説明しますが、イメージの最適化など、その他の関連トピックについても取り上げます。

選択した Dockerfile のベストプラクティスをトピックごとにグループ分けしました。Dockerfile のベストプラクティスは、開発プロセス全体の一部に過ぎません。イメージの構築前後に適用すべき、関連するコンテナイメージのセキュリティおよびシフト・レフトのセキュリティリソースを紹介するセクションも最後に掲載しています。

#1 不要な特権を回避する

これらのヒントは、最小特権原則に従っているため、サービスやアプリケーションは、その目的を実行するために必要なリソースと情報のみにアクセスできます。

#1.1 ルートレスコンテナ

2021年のレポートでは、58% のイメージがコンテナのエントリポイントを root (UID 0) として実行していることが明らかになりました。しかし、Dockerfile では、そうしないことがベストプラクティスです。コンテナを root として実行する必要があるユースケースはごくわずかです。そのため、デフォルトの実効 UID を root 以外のユーザーに変更する USER 命令を必ず含めるようにしてください。

さらに、実行環境によっては、root として実行されているコンテナがデフォルトでブロックされる場合があります(Openshift では、追加の SecurityContextConstraints が必要です)。

非 root として実行するには、Dockerfile にいくつかの手順を追加する必要があります。

  • 1. USER 命令で指定したユーザーがコンテナ内に存在することを確認します。
  • 付与します。
FROM alpine:3.12
# Create user and set ownership and permissions as required
RUN adduser -D myuser && chown -R myuser /myapp-data
# ... copy application files
USER myuser
ENTRYPOINT ["/myapp"]Code language: PHP (php)

root で起動し、gosu または su-exec を使用して標準ユーザーに切り替えるコンテナがあります。

また、コンテナが root として非常に特定のコマンドを実行する必要がある場合は、sudo を使用する場合があります。

これらの 2 つの方法は root として実行するよりも望ましいですが、Openshift のような制限のある環境では機能しない場合があります。

#1.2 特定の UID にバインドしないでください

コンテナを root ユーザー以外で実行しますが、そのユーザーの UID を要件にしないでください。

理由

  • Openshift は、デフォルトでコンテナの実行時にランダムな UID を使用します。
  • 特定の UID(例:最初の標準ユーザーである UID 1000)を強制すると、データ永続化用のホストフォルダーなどのバインドマウントの権限を調整する必要があります。または、コンテナをホストの UID で実行する場合(-uオプションを Docker で指定)、コンテナ内のフォルダーから読み書きを試行するとサービスが停止する可能性があります。
...
RUN mkdir /myapp-tmp-dir && chown -R myuser /myapp-tmp-dir
USER myuser
ENTRYPOINT ["/myapp"]
Code language: JavaScript (javascript)

このコンテナは、myuser以外の UID で実行すると問題が発生します。アプリケーションが/myapp-tmp-dirフォルダに書き込みできないためです。

myuser のみが書き込み可能なハードコーディングされたパスを使用しないでください。代わりに、一時データを/tmp(スティッキービット権限により、すべてのユーザーが書き込み可能)に書き込んでください。リソースを世界読み取り可能(例:0644 ではなく 0640)にし、UID が変更された場合でも正常に動作することを確認してください。

...
USER myuser
ENV APP_TMP_DATA=/tmp
ENTRYPOINT ["/myapp"]
Code language: PHP (php)


この例では、アプリケーションは APP_TMP_DATA 環境変数にあるパスを使用します。デフォルト値 /tmp を使用すると、アプリケーションは任意の UID として実行でき、一時データを /tmpに書き込むことができます。パスを構成可能な環境変数として設定することは必ずしも必要ではありませんが、永続化のためのボリュームの設定やマウントが簡単になります。

#1.3 実行ファイルを root ユーザー所有で書き込み不可にする

コンテナ内のすべての実行ファイルは、非 root ユーザーによって実行される場合でも、root ユーザー所有であり、世界書き込み不可であることが Dockerfile のベストプラクティスです。

これにより、実行ユーザーが既存のバイナリやスクリプトを改変できなくなり、さまざまな攻撃を防止できます。このベストプラクティスに従うことで、コンテナの不変性を効果的に強制できます。不変のコンテナは実行時にコードを自動的に更新しないため、実行中のアプリケーションが誤ってまたは悪意を持って改変されるのを防ぐことができます。

このベストプラクティスに従うため、以下の点を避けてください:

...
WORKDIR $APP_HOME
COPY --chown=app:app app-files/ /app
USER app
ENTRYPOINT /app/my-app-entrypoint.sh
Code language: PHP (php)

ほとんどの場合、--chown app:app オプション(または RUN chown ... コマンド)を省略できます。app ユーザーは、ファイルの実行権限のみが必要であり、所有権は不要です。

クラウドとコンテナを保護する ための5つのセキュリティベストプラクティス

コンテナの安全を確保しながら、イノベーションのスピードに対応しましょう。

#2 攻撃対象領域を削減します

イメージを最小限に抑えることが Dockerfile のベストプラクティスです。

不要なパッケージを含めないようにし、ポートを公開しないことで、攻撃対象領域を削減します。コンテナ内に含めるコンポーネントが多いほど、システムはより露出度が高くなり、特に自分の管理下にはないコンポーネントの場合、メンテナンスが難しくなります。

#2.1 マルチステージビルド

マルチステージビルド機能を使用して、コンテナ内で再現可能なビルドを実現します。

マルチステージビルドでは、最終的な成果物(つまり、最終的な実行ファイル)をコンパイルまたは生成するために必要なすべてのツールを含む中間コンテナ(ステージ)を作成します。次に、追加の開発関連コンポーネントや一時的なビルドファイルなど、結果の成果物だけを最終イメージにコピーします。

適切に作成されたマルチステージビルドでは、最終イメージには、必要最小限のバイナリと関連コンポーネントのみが含まれ、ビルドツールや中間ファイルは含まれません。これにより、攻撃対象領域が減少して脆弱性が減少します。

安全性が向上するだけでなく、イメージのサイズも縮小されます。

Go アプリケーションの場合、マルチステージビルドの例は次のようになります。

#This is the "builder" stage
FROM golang:1.15 as builder
WORKDIR /my-go-app
COPY app-src .
RUN GOOS=linux GOARCH=amd64 go build ./cmd/app-service
#This is the final stage, and we copy artifacts from "builder"
FROM gcr.io/distroless/static-debian10
COPY --from=builder /my-go-app/app-service /bin/app-service
ENTRYPOINT ["/bin/app-service"]Code language: PHP (php)


これらの Dockerfile の指示により、go ツールチェーンをすべて含む golang:1.15 コンテナを使用して、ビルダーステージを作成します。

FROM golang:1.15 as builder
Code language: JavaScript (javascript)

そこにソースコードをコピーしてビルドすることができます。

WORKDIR /my-go-app
COPY app-src .
RUN GOOS=linux GOARCH=amd64 go build ./cmd/app-service

次に、Debian のディストリビューションレスイメージ(次のヒントを参照)に基づいて、別のステージを定義します。

FROM gcr.io/distroless/static-debian10Code language: JavaScript (javascript)

コピー--from=builder フラグを使用して、ビルダーステージで生成された実行ファイルをコピーします。

COPY --from=builder /my-go-app/app-service /bin/app-service
Code language: JavaScript (javascript)

最終的なイメージには、distroless/static-debian-10 イメージの最小限のライブラリセットと、アプリの実行ファイルのみが含まれます。

ビルドツールチェーンもソースコードも一切含まれません。

NodeJS アプリケーションの例、またはDjango マルチステージビルドを使用した効率的な Python を確認することをお勧めします。

#2.2 Distroless、ゼロから

Dockerfile のベストプラクティスに従うため、必要最小限のベースコンテナを使用します。

理想的には、コンテナをゼロから作成しますが、100% 静的なバイナリしか機能しません。

Distroless は、その代替として優れた選択肢です。これらは、Go、Python、その他のフレームワークの実行に必要な最小限のライブラリのみを含むように設計されています。

たとえば、汎用的な ubuntu:xenialイメージをコンテナのベースとする場合、次のように記述します。

FROM ubuntu:xenial-20210114
Code language: CSS (css)


Sysdig インラインスキャナーによって検出された、100 以上の脆弱性を含めることになります。これらは、含めている大量のパッケージに関連しており、おそらく必要も使用もされないでしょう。

❯ docker run -v /var/run/docker.sock:/var/run/docker.sock --rm quay.io/sysdig/secure-inline-scan:2 image-ubuntu -k $SYSDIG_SECURE_TOKEN --storage-type docker-daemon
Inspecting image from Docker daemon -- distroless-1:latest
  Full image:  docker.io/library/image-ubuntu
  Full tag:    localbuild/distroless-1:latest
…
Analyzing image…
Analysis complete!
...
Evaluation results
 - warn dockerfile:instruction Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check
 - warn dockerfile:instruction Dockerfile directive 'USER' not found, matching condition 'not_exists' check
 - warn files:suid_or_guid_set SUID or SGID found set on file /bin/mount. Mode: 0o104755
 - warn files:suid_or_guid_set SUID or SGID found set on file /bin/su. Mode: 0o104755
 - warn files:suid_or_guid_set SUID or SGID found set on file /bin/umount. Mode: 0o104755
 - warn files:suid_or_guid_set SUID or SGID found set on file /sbin/pam_extrausers_chkpwd. Mode: 0o102755
 - warn files:suid_or_guid_set SUID or SGID found set on file /sbin/unix_chkpwd. Mode: 0o102755
 - warn files:suid_or_guid_set SUID or SGID found set on file /usr/bin/chage. Mode: 0o102755
…
Vulnerabilities report
   Vulnerability    Severity Package                                  Type     Fix version      URL
 - CVE-2019-18276   Low      bash-4.3-14ubuntu1.4                     dpkg     None             http://people.ubuntu.com/~ubuntu-security/cve/CVE-2019-18276
 - CVE-2016-2781    Low      coreutils-8.25-2ubuntu3~16.04            dpkg     None             http://people.ubuntu.com/~ubuntu-security/cve/CVE-2016-2781
 - CVE-2017-8283    Negligible dpkg-1.18.4ubuntu1.6                     dpkg     None             http://people.ubuntu.com/~ubuntu-security/cve/CVE-2017-8283
 - CVE-2020-13844   Medium   gcc-5-base-5.4.0-6ubuntu1~16.04.12       dpkg     None             http://people.ubuntu.com/~ubuntu-security/cve/CVE-2020-13844
...
 - CVE-2018-20839   Medium   systemd-sysv-229-4ubuntu21.29            dpkg     None             http://people.ubuntu.com/~ubuntu-security/cve/CVE-2018-20839
 - CVE-2016-5011    Low      util-linux-2.27.1-6ubuntu3.10            dpkg     None             http://people.ubuntu.com/~ubuntu-security/cve/CVE-2016-5011
Code language: JavaScript (javascript)


コンテナに gcc コンパイラまたは systemd SysV 互換性が必要ですか?おそらく必要ないでしょう。dpkg や bash も同様です。

イメージを gcr.io/distroless/base-debian10 ベースにしている場合:

FROM gcr.io/distroless/base-debian10


その場合、glibclibsslopenssl などの必要なライブラリのみを含む基本的なパッケージセットのみが含まれます。

libc を必要としない Go のような静的コンパイルアプリケーションの場合は、さらにスリムな方法も利用できます。

FROM gcr.io/distroless/static-debian10
Code language: JavaScript (javascript)

#2.3 信頼できるベースイメージを使用する

イメージのベース(FROM 命令)は慎重に選択してください。

信頼できない、またはメンテナンスされていないイメージをベースにして構築すると、そのイメージのすべての問題や脆弱性がコンテナに継承されます。

ベースイメージを選択するには、Dockerfile のベストプラクティスに従ってください。

  • 未知のユーザーによって構築されたイメージよりも、信頼できるリポジトリやプロバイダが提供する検証済み公式イメージを優先してください。
  • カスタムイメージを使用する場合は、イメージのソースと Dockerfile を確認し、独自のベースイメージを構築してください。パブリックレジストリで公開されているイメージが、指定された Dockerfile から実際に構築されているという保証はありません。また、そのイメージが常に最新の状態に保たれているという保証もありません。
  • セキュリティやミニマリズムの観点から、公式のイメージが最適ではない場合もあります。たとえば、公式の node イメージbitnami/node イメージを比較すると、後者は minideb ディストリビューション上にカスタマイズされたバージョンを提供しています。これらは、最新のバグ修正で頻繁に更新され、Docker Content Trust で署名され、セキュリティスキャンで既知の脆弱性が検出されていません。
Diagram of the layer tree of an image. If one layer is compromised, all the following layers will probably be compromised as well

#2.4 イメージを頻繁に更新してください

頻繁に更新されるベースイメージを使用し、その上に独自のイメージを再構築してください。

新しいセキュリティの脆弱性は絶えず発見されているため、最新のセキュリティパッチを適用することが一般的なセキュリティのベストプラクティスです。

壊れる変更が含まれている可能性のある最新バージョンに常にアップグレードする必要はありませんが、バージョン管理戦略を定義してください。

  • 安定または長期サポートバージョンを使用してください。これらのバージョンでは、セキュリティの修正が迅速かつ頻繁に提供されます。
  • 事前に計画を立ててください。ベースイメージのバージョンがサポート終了となり、更新の配信が停止される前に、古いバージョンを削除して移行する準備をしておいてください。
  • また、定期的に、同様の戦略に従って独自のイメージを再構築し、ベースディストリビューション、Node、Golang、Python などから最新のパッケージを取得してください。npmgo mod などのほとんどのパッケージまたは依存関係マネージャーには、最新のセキュリティアップデートに対応するためにバージョン範囲を指定する方法が用意されています。

#2.5 公開ポート

コンテナで開いているポートはすべて、システムへの入り口となります。アプリケーションに必要なポートのみを公開し、SSH (22) などのポートは公開しないでください。

Dockerfile には EXPOSE コマンドがありますが、このコマンドは情報提供および文書化のみを目的としたものであり、 ポートを公開しても、コンテナを実行した際にすべての公開ポートへの接続が自動的に許可されるわけではありません(docker run --publish-allを使用する場合を除く)。コンテナを実行する際には、実行時に公開するポートを指定する必要があります。

Dockerfile では EXPOSE を使用して必要なポートのみをフラグ付けしドキュメント化し、公開または実行時にそれらのポートに限定して使用してください。

#3 機密データの漏洩を防ぐ

コンテナを扱う際には、機密データに十分注意してください。

以下の Dockerfile のベストプラクティスでは、コンテナの認証情報の取り扱い、および不要なファイルや情報の漏洩を防ぐ方法について、いくつかのアドバイスをご紹介します。

#3.1 認証情報と機密性

Dockerfile の指示(環境変数、引数、またはコマンドにハードコード)に秘密情報や認証情報を絶対に記載しないでください。

コンテナにコピーされるファイルには特に注意してください。Dockerfile の後の指示でファイルが削除された場合でも、そのファイルは実際には削除されず、最終的なファイルシステムでは「非表示」になっているだけなので、前のレイヤーからアクセスすることができます。したがって、イメージを構築する際には、以下の慣習に従ってください。

  • アプリケーションが環境変数による設定をサポートしている場合は、それを使用して実行時に秘密情報を設定します(docker run の -e オプション)。または、Docker secretsKubernetes secretsを使用して、環境変数として値を提供します。
  • 設定ファイルを使用し、設定ファイルを Docker にバインドマウントするか、Kubernetes secretsからマウントします。

また、イメージには、機密情報や、特定の環境 (本番、ステージングなど) に結びつく設定値を含めないでください。

その代わりに、実行時に値を挿入することで、イメージをカスタマイズできるようにしてください。特に、シークレットは注意してください。例として、安全な値またはダミーの値のみを含む設定ファイルのみを含めるようにしてください。

#3.2 ADD、COPY

ADD および COPY 命令は、Dockerfile で同様の機能を提供します。ただし、COPY はより明示的です。

URL や tar ファイルからファイルを追加する場合など、ADD 機能が必要でない限りは COPY を使用してください。COPY はより予測可能で、エラーが発生しにくいです。

一部のケースでは、curlwget を使用してパッケージをダウンロードし、展開し、元のファイルを削除する一連の操作を単一のステップで実行し、レイヤーの数を減らすために、ADD ではなく RUN 命令を使用することが推奨されます。

マルチステージビルドもこの問題を解決し、Dockerfile のベストプラクティスに従うのに役立ちます。これにより、前のステージから最終的に展開されたファイルのみをコピーできます。

#3.3 コンテキストと dockerignore を構築します

以下は、デフォルトの Dockerfile を使用し、現在のフォルダをコンテキストとして、docker を使用してビルドを実行した典型的な例です。

docker build -t myimage .


注意!

「.」パラメータはビルドコンテキストです。「.」をコンテキストとして使用すると、設定ファイル、認証情報、バックアップ、ロックファイル、一時ファイル、ソース、サブフォルダ、ドットファイルなど、機密情報や不要なファイルがコンテナにコピーされる危険があります。

Dockerfile 内に次のようなコマンドがあると想像してみてください。

COPY . /my-app

これにより、ビルドコンテキスト内のすべてがコピーされます。この例の場合、「.」には Dockerfile 自体も含まれます。

Dockerfile のベストプラクティスとしては、コンテナ内にコピーする必要のあるファイルを含むサブフォルダを作成し、それをビルドコンテキストとして使用し、可能であれば COPY 命令で明示的に指定することです(ワイルドカードの使用は避けてください)。例えば、次のようにします。

docker build -t myimage files/

また、ファイルやディレクトリを明示的に除外するための .dockerignore ファイルを作成してください。

COPY 命令に細心の注意を払っても、イメージのビルドを開始する前に、ビルドコンテキストのすべてが Docker デーモンに送信されます。つまり、ビルドコンテキストを小さく制限することで、ビルドの速度が向上します。

ビルドコンテキストを独自のフォルダに保存し、.dockerignore を使用して可能な限り削減してください。

クラウドとコンテナを保護する ための5つのセキュリティベストプラクティス

コンテナの安全を確保しながら、イノベーションのスピードに対応しましょう。

#4 その他

#4.1 レイヤーの整合性

Dockerfile の指示の順序は非常に重要であることを覚えておいてください。

RUN、COPY、ADD などの指示は新しいコンテナレイヤーを作成するため、複数のコマンドをグループ化することでレイヤーの数を減らすことができます。

たとえば、次のようにします。

FROM ubuntu
RUN apt-get install -y wget
RUN wget https://…/downloadedfile.tar
RUN tar xvzf downloadedfile.tar
RUN rm downloadedfile.tar
RUN apt-get remove wget
Code language: JavaScript (javascript)

Dockerfile では、次のように行うことがベストプラクティスです。

FROM ubuntu
COPY source/* .
Run apt-get install nodejs
ENTRYPOINT ["/usr/bin/node", "/main.js]

下記の方がさらに良いでしょう。

FROM ubuntu
RUN apt-get install nodejs
COPY source/* .
ENTRYPOINT ["/usr/bin/node", "/main.js"]
Code language: JavaScript (javascript)


nodejs パッケージは、アプリケーションのソースよりも変更される可能性が低いです。

rm コマンドを実行すると、次のレイヤーのファイルは削除されますが、最終的なイメージファイルシステムは、それ以前のすべてのレイヤーで構成されるため、そのファイルは引き続き利用可能であり、アクセス可能になります。

したがって、機密ファイルをコピーしてから削除しないでください。最終的なコンテナファイルシステムではそのファイルは表示されなくなりますが、引き続き簡単にアクセス可能になります。

#4.2 メタデータラベル

イメージを構築する際には、メタデータラベルを含めることが Dockerfile のベストプラクティスです。

ラベルは、アプリケーションのバージョン、ウェブサイトへのリンク、メンテナへの連絡方法など、イメージの管理に役立ちます。

以前の ラベルスキーマ標準草案を廃止する、OCI イメージ仕様の事前定義された注釈をご覧ください。

#4.3 リント

Haskell Dockerfile Linter (hadolint) などのツールは、Dockerfile 内の不適切な慣習を検出し、RUN 命令によって実行されるシェルコマンド内の問題も明らかにします。

このようなツールを CI パイプラインに組み込むことを検討してください。

イメージスキャナも、カスタマイズ可能なルールによって不適切な慣習を検出し、イメージの脆弱性とともに報告することができます。

Image scanning policies in Sysdig Secure. You can create gates to check for misconfigurations in the Dockerfile.

検出できる設定ミスには、root として実行されているイメージ、公開されているポート、ADD 命令の使用、ハードコードされた秘密情報、または使用を推奨しない RUN コマンドなどがあります。

#4.4 開発中にイメージをローカルでスキャンする

イメージのスキャンは、コンテナを実行する前に潜在的な問題を検出するためのもう 1 つの方法です。イメージスキャンのベストプラクティスを順守するには、イメージがコンテナレジストリにプッシュされたときだけでなく、イメージのライフサイクルのさまざまな段階でスキャンを実行する必要があります。

イメージが構築されたらすぐに、レジストリにプッシュする前に CI パイプラインでイメージを直接スキャンして、「シフト・レフト・セキュリティ」のパラダイムを適用することが、セキュリティのベストプラクティスです。

これには、開発者のコンピュータSysdig インラインスキャナを使用することも含まれます。このスキャナは、JenkinsGithub actionsその他の CI/CD ツールとのさまざまな統合機能を提供します。

スキャンしたイメージは、現時点では「安全」であるかもしれませんが、時間が経つにつれて新しい脆弱性が発見され、危険になる可能性があります。

定期的に新しい脆弱性を再評価してください。

Diagram of a vulnerability timeline. A vulnerability exists in software before they are detected. You may deploy images that are vulnerable, the vulnerability may be discovered later. This means your were vulnerable all the time, so you need to continuosly scan your images running in production to protect from these newly discovered vulnerabilities.

#5 イメージの構築を超えて

ここまで、イメージの構築プロセスに焦点を当て、最適な Dockerfile を作成するためのヒントについて説明してきました。しかし、イメージの構築前に確認すべき事項や、構築後に実行すべき事項、つまりイメージの実行についても忘れてはなりません。

#5.1 Docker ポートソケットと TCP 保護

Docker ソケットは、ホストシステムへの大きな特権ドアであり、最近見られたように、侵入や悪意のあるソフトウェアの使用に利用される可能性があります。/var/run/docker.sock の権限が正しいことを確認し、Docker が TCP 経由で公開されている場合(これはまったく推奨されません)、それが適切に保護されていることを確認してください。

#5.2 イメージの署名と署名の検証

docker content trust、Docker notary、Harbor notary、または同様のツールを使用してイメージにデジタル署名し、実行時にそれらを検証することは、Dockerfile のベストプラクティスの 1 つです。

署名検証の有効化は、実行環境ごとに異なります。たとえば、docker では、DOCKER_CONTENT_TRUST環境変数を使用して行います。

export DOCKER_CONTENT_TRUST=1

#5.3 タグの変更可能性

コンテナの世界では、タグは特定の時点における具体的なイメージのバージョンへの揮発的な参照です。

If you use mutant tags, you might be scanning one version, but deploying another one.

タグは予期せず、いつでも変更される可能性があります。詳細については、「変異タグの攻撃」をご覧ください。

#5.4 ルート以外のユーザーとして実行

先ほど、コンテナの構築にはルート以外のユーザーを使用することについて述べました。USER 命令はコンテナのデフォルトユーザーを設定しますが、実行中のコンテナの実際のユーザーを決定するのは、オーケストレーターまたは実行環境(docker run、kubernetes など)です。

root として環境を実行することは絶対に避けてください

Openshiftや一部のKubernetesクラスターでは、デフォルトで制限的なポリシーが適用され、rootコンテナの実行が禁止されています。権限や所有権の問題を回避するためにrootとして実行する誘惑に負けないでください。代わりに、根本的な問題を解決してください。

#5.5 ヘルス/ライブチェックを含める

プレーンな Docker または Docker Swarm を使用する場合、可能な限り Dockerfile に HEALTHCHECK 命令を含めてください。これは、サービスを正常に動作させ、必要に応じてサービスを再起動するために、長時間実行または永続的なサービスにとって非常に重要です。

Kubernetes でイメージを実行する場合は、docker HEALTHCHECK 命令は適用されないため、コンテナ定義内で livenessProbe 設定を使用してください。

#5.6 機能の削除

また、実行時には、Docker の --cap-drop フラグ または Kubernetes の securityContext.capabilities.drop を使用して、アプリケーションの機能を必要最小限に制限することができます。そうすることで、コンテナが侵害された場合でも、攻撃者が実行できる操作の範囲を制限することができます。

また、コンテナの特権を制限する追加のメカニズムとして AppArmor および Seccomp を適用する方法の詳細については、以下をご覧ください。

結論

コンテナイメージのセキュリティは、深刻な結果をもたらすまで無視できない、複雑かつ重要な課題であることがわかりました。

セキュリティ体制を強化し、管理オーバーヘッドを削減するには、予防とセキュリティのシフト・レフトが不可欠です。

Dockerfile のベストプラクティスに焦点を当てた一連の推奨事項は、この課題の解決に役立ちます。

さらに一歩進んだ対応をご希望の場合は、12 のコンテナイメージスキャンに関するベストプラクティスの記事もご参照ください。セキュリティのシフト・レフトに役立ちます。

Sysdig Secure のイメージスキャン機能は、これらの Dockerfile のベストプラクティスに従うのに役立ちます。脆弱性や設定ミスをチェックして、脅威が展開される前に対応することで、セキュリティのシフト・レフトを実現します。設定はわずか数分で完了します。こちらで個別デモも受け付けています。

クラウドとコンテナを保護する ための5つのセキュリティベストプラクティス

コンテナの安全を確保しながら、イノベーションのスピードに対応しましょう。