はじめに
Dockerコンテナを使用しているエンジニアの中で、最近話題になっているのがDistrolessイメージです。この記事では、Distrolessの概要と、特にPython向けのカスタムDistrolessイメージを作成する方法を紹介します。
Distrolessとは?
Distrolessとは、アプリケーションの実行に必要な最低限のファイルやライブラリだけを含んだ軽量なコンテナイメージのことです。通常のLinuxディストリビューションでは、シェルやパッケージマネージャなど、コンテナ内で使用しないものも多く含まれますが、Distrolessはこれらを排除し、よりセキュアで軽量なイメージを提供します。
例えば、通常のDebianベースのイメージでは多くのOSファイルが含まれますが、Distrolessでは不要な部分が削除され、攻撃の対象となる 攻撃面積(Attack Surface) が大幅に減少します。
なぜDistrolessを使うのか?
Distrolessイメージを使用する最大の利点は次の2つです。
-
セキュリティの強化
- Distrolessには、シェルやその他の不要なツールが含まれていないため、脆弱性のリスクが低減されます。これは、使用しないパッケージに脆弱性が存在しても、その影響を受けにくいという意味で非常にセキュアです。
-
軽量
- 最小限のファイルしか含まれていないため、コンテナイメージのサイズが非常に小さく、起動時間の短縮やリソースの節約につながります。たとえば、通常のDebianイメージが100MB以上あるのに対し、Distrolessイメージは20MB以下に収まることもあります。
DistrolessのPythonイメージの課題
Googleが提供するgcr.io/distroless/python3
は、まだ実験的なもので、本番環境での使用は推奨されていません。脆弱性が報告されている場合もあり、更新頻度が低いことが問題となっています。そのため、最新のPythonと必要なライブラリを含んだカスタムDistrolessイメージを作成することが推奨されます。
Distroless Pythonイメージの作成方法
それでは、Distroless Pythonイメージを作成する手順を解説します。この記事では、最新のPythonと必要なライブラリをDistrolessベースに組み込んだ軽量イメージを作成します。
カスタムDockerfileの例
# Stage 1: Pythonをビルドするためのステージ
FROM python:3.10-slim as python-builder
# Flaskなどの必要なパッケージをインストール
RUN pip install --no-cache-dir flask numpy
# Stage 2: Distrolessベースの最小イメージを準備
FROM gcr.io/distroless/base-debian11
# Pythonバイナリをビルドステージからコピー
COPY --from=python-builder /usr/local/lib/python3.10 /usr/local/lib/python3.10
COPY --from=python-builder /usr/local/bin/python3.10 /usr/local/bin/python3.10
# アプリケーションのソースコードをコピー
COPY ./app /app
# 作業ディレクトリを設定
WORKDIR /app
# Flaskアプリケーションを実行
ENTRYPOINT ["/usr/local/bin/python3.10", "app.py"]
解説
-
マルチステージビルド
最初のステージでPythonをインストールし、必要なパッケージ(flaskやnumpyなど)をセットアップします。次のステージでは、Distrolessベースの軽量イメージにPythonと必要なライブラリをコピーします。これにより、不要なファイルを含まないクリーンなイメージを作成できます。 -
非rootユーザーの設定
コンテナ内での操作は、セキュリティを強化するために非rootユーザーで行うことを推奨します。 -
Pythonのエントリポイント設定
最後に、Pythonアプリケーションを実行するエントリポイントを設定します。これにより、コンテナが起動すると自動的にアプリケーションが実行されます。
Distrolessの利点と課題
Distrolessは、セキュリティと軽量性に大きなメリットがありますが、デバッグが難しいという課題もあります。シェルが含まれていないため、コンテナ内での操作が制限されます。デバッグのためには、別途-debug版のイメージを用意するか、ログ設計を工夫する必要があります。
まとめ
Distrolessイメージを活用することで、コンテナのセキュリティを強化し、より効率的な運用が可能です。特に、Pythonのような高機能な言語でも、自分でカスタマイズしたDistrolessイメージを作成すれば、最新の環境で動作する軽量なコンテナを実現できます。この記事を参考に、ぜひあなたのプロジェクトでもDistrolessを活用してみてください。
参考情報
備考
OCIマニフェストの使用
2023年3月以降、DistrolessイメージはOCIマニフェストを使用しています。もしapplication/vnd.oci.image.manifest.v1+json
やapplication/vnd.oci.image.index.v1+json
に関するエラーが発生した場合は、使用しているコンテナツール(DockerやJibなど)を最新バージョンにアップデートしてください。
イメージの検証
全てのDistrolessイメージは、cosignで署名されています。イメージを使用する前に、その署名を検証することを推奨します。署名の検証は以下のコマンドで行えます。
cosign verify $IMAGE_NAME --certificate-oidc-issuer https://accounts.google.com --certificate-identity keyless@distroless.iam.gserviceaccount.com
エントリポイントの形式
Distrolessイメージにはデフォルトでシェルが含まれていないため、ENTRYPOINT
は必ずベクタ形式で指定する必要があります。例えば、以下のように設定します。
ENTRYPOINT ["myapp"]
この形式でないと、コンテナランタイムが自動的にシェルをプレフィックスとして追加し、エラーが発生します。
デバッグイメージ
Distrolessイメージにはデフォルトでシェルが含まれていませんが、debug
タグが付いたイメージにはbusybox
が含まれており、デバッグ用にシェルアクセスが可能です。
例
FROM gcr.io/distroless/python3-debian12:debug
COPY . /app
WORKDIR /app
CMD ["hello.py", "/etc"]
デバッグ用イメージをビルドして、シェルエントリポイントで起動することができます。
docker run --entrypoint=sh -ti my_debug_image
これにより、コンテナ内でファイルの確認やデバッグが可能になります。
公式サポートされるイメージ
Distrolessプロジェクトでは、様々なDebian 12ベースのイメージが提供されています。以下が代表的なものです。
gcr.io/distroless/static-debian12
gcr.io/distroless/python3-debian12
gcr.io/distroless/java-base-debian12
詳細は公式リポジトリのサポートポリシーを参照してください。