9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Pythonのdistrolessコンテナを使って脆弱性を撲滅した話

Last updated at Posted at 2022-12-06

はじめに

  • AWS ECS+ECRで動いているpythonのサービスがあった
    • ただし、ECRのスキャン機能でものすごい数の脆弱性が出ていた...
  • 1つずつ解消していくのは現実的ではないため、distrolessコンテナを導入することになった

distrolessとは

  • Googleが提供しているコンテナイメージ
  • アプリケーションとそのランタイム依存関係のみ含まれる(=必要最小限)
    • パッケージマネージャー、シェルなどは含まれない
  • 導入メリットとして、①軽量であること、②セキュアであることが挙げられる

やったことざっくりと

  • 以前は「python:3.9.13-slim-buster」のイメージを使用してビルドしていた
    • これを1段階目「python:3.9.13-slim-buster」→2段階目「gcr.io/distroless/python3」のマルチステージビルドにする
  • 1段階目
    • パッケージをインストールし、コピー用ディレクトリに置く
    • コードをコピー用ディレクトリに展開する
  • 2段階目
    • PYTHONPATHにパッケージのパスを追加する
    • 1段階目のコピー用ディレクトリからコピーする

辿り着いたDockerfile(一部省略)

  • ARGの内容は、実行時に --build-arg で引数として指定する運用
  • RUNNER_IMAGE_NAME にdistrolessコンテナイメージを設定している
    • dev環境の場合は gcr.io/distroless/python3:debug
      • :debug のイメージにはshellが含まれているため
    • stg, prod環境の場合は gcr.io/distroless/python3
  • APP_NAME = コードが格納されたディレクトリ
ARG RUNNER_IMAGE_NAME

// ここから1段階目
FROM python:3.9.13-slim-buster AS builder

ARG APP_NAME
ARG DC_TZ
ARG ...

COPY requirements.txt /tmp/

RUN set -x \
 && \
 : "timezones" \
 && cp /usr/share/zoneinfo/${DC_TZ} /etc/localtime \
 && cp -a --parents /etc/localtime /opt \
 && \
 : "lib install from pip" \
 && mv /tmp/requirements.txt ./ \
 && pip3 install --upgrade pip \
 && pip3 install --no-cache-dir -r requirements.txt \
 && cp -a --parents /usr/local/lib/python3.9/site-packages /opt

COPY ${APP_NAME} /opt/opt/${APP_NAME}

// ここから2段階目
FROM ${RUNNER_IMAGE_NAME}

ARG APP_NAME
ARG DC_LANG
ARG ...

ENV LANG ${DC_LANG}
ENV ...
ENV PYTHONPATH=/usr/local/lib/python3.9/site-packages:/opt/${APP_NAME}/libs:/opt/${APP_NAME}

COPY --from=builder /opt /

WORKDIR /opt/${APP_NAME}

CMD ["***.py"]

ポイント

パッケージのインストール場所とコピー場所

 && pip3 install --upgrade pip \
 && pip3 install --no-cache-dir -r requirements.txt \
 && cp -a --parents /usr/local/lib/python3.9/site-packages /opt
  • (1段階目)pipインストールしたパッケージが入っているディレクトリをコピー用ディレクトリ(/opt)にコピー
  • 私はこれを忘れていてしばらく詰まりました
COPY ${APP_NAME} /opt/opt/${APP_NAME}
  • (1段階目)コードをコピー用ディレクトリにコピー
  • 運用上、コードを opt/${APP_NAME} というディレクトリ構造で格納したいため、/opt(コピー用ディレクトリ)/opt(格納用ディレクトリ)という指定に...(コピー用ディレクトリの名前をtempとかに変えればよかった)
ENV PYTHONPATH=/usr/local/lib/python3.9/site-packages:/opt/${APP_NAME}/libs:/opt/${APP_NAME}
  • (2段階目)パッケージが入っているディレクトリをPYTHONPATHに追加
COPY --from=builder /opt /
  • (2段階目)1段階目のコピー用ディレクトリ(/opt)の中身をコピー
  • これでインストールしたパッケージもコードも使えるようになる

CMDの変更

// 変更前
CMD ["python3", "***.py"]

// 変更後
CMD ["***.py"]

成果

スクリーンショット 2022-12-06 17.54.17.png

  • あんなにあった脆弱性がなくなった!
  • サイズも削減された!

今後に向けての課題

  • python3のdistrolessは本番運用向きではないらしい...
    • https://github.com/GoogleContainerTools/distroless
    • The following images are also published on gcr.io, but are considered experimental and not recommended for production usage: ...
    • 今回は内部向けのサービスだったため踏み切ったが、外部向けに展開するサービスには向いていないかも
  • 今回のサービスはパッケージも少なめだったが、複雑なサービスになったときに動作がどこまで保証されるか未検証

参考記事

実装時、大変お世話になりました!

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?