1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

【Finch版】distrolessイメージを使ってイメージサイズを改善する

Last updated at Posted at 2024-06-23

はじめに

この記事では既存のコンテナイメージをdistrolessイメージを使って改善していく記事です。
主な内容としては実践したときのメモを中心に書きます。
(忘れやすいことなど)誤りなどがあれば書き直していく予定です。

今回利用したソースコードは以下のリポジトリにあります。

distroless_docker_image GitHub

環境

今回は以下の環境で動作確認を行っています。そのほかの環境で動かす場合の参考にしてください。

  • MacBook
    • Apple Sillicon M1
    • Sonoma 14.0
  • Python
    • Python 3.9

※Python3.9と記載していますが、dockerイメージにおけるPythonです。

なお、Finchのセットアップについてはココを参照してください。

既存のコンテナイメージ

今回改善するイメージは以下です。

FROM python:3.9-alpine as builder

RUN apk add --no-cache musl-dev mysql-dev gcc
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir --upgrade pip && pip install --no-cache-dir -r requirements.txt

CMD ["python", "main.py"]

imageを構築する過程でpipを実行しています。pipでインストールするパッケージは以下のとおりです。

requirements.txt
alembic==1.13.1
annotated-types==0.6.0
boto3==1.4.8
botocore==1.8.11
certifi==2023.11.17
charset-normalizer==3.3.2
docutils==0.14
exceptiongroup==1.2.0
functions==0.7.0
greenlet==3.0.3
idna==3.6
iniconfig==2.0.0
jmespath==0.9.3
Mako==1.3.0
MarkupSafe==2.1.3
mysqlclient==2.2.1
packaging==23.2
pluggy==1.3.0
pydantic==2.5.3
pydantic_core==2.14.6
pytest==7.4.4
python-dateutil==2.6.1
python-multipart==0.0.6
pytz==2023.3.post1
requests==2.31.0
s3transfer==0.1.12
schemas==0.7.1
six==1.11.0
SQLAlchemy==2.0.25
SQLAlchemy-Utils==0.41.1
tomli==2.0.1
typing_extensions==4.9.0
urllib3==2.1.0
xmltodict==0.13.0

なお、mysqlclientをインストールしているため、apkでmysql-devをインストールしています。
イメージをビルドします。

セットアップ

まずはVMを初期化します。

finch vm init

※すでに初期化している場合は下記のような実行結果が表示されます。

FATA[0000] the instance "finch" is already running

python:3.9-alpineイメージをビルドする

では、Finchでイメージをビルドしていきましょう。以下のコマンドを実行します。

finch build -t test_alpine:1 .

サイズを確認するため、finch imagesを実行します。

finch images

実行結果は以下のとおりです。

REPOSITORY     TAG    IMAGE ID        CREATED          PLATFORM       SIZE         BLOB SIZE
test_alpine    1      d77ee33a7032    3 seconds ago    linux/arm64    337.2 MiB    104.2 MiB

サイズは337MBです。このコンテナイメージをdistrolessイメージに置き換えていきます。

distrolessイメージを使って改善していく

まずはどんな感じのdockerfileになるかを確認します。

FROM python:3.9-alpine as builder

WORKDIR /app
COPY . .
RUN pip --no-cache-dir install --upgrade pip && pip install --no-cache-dir --target site-packages -r requirements.txt

FROM gcr.io/distroless/python3-debian11:nonroot

WORKDIR /app
COPY --from=builder /app .
ENV PYTHONPATH=/app/site-packages
CMD ["./main.py"]

なお、requirements.txtは以下のとおりです。変更点としてはmysqlclientを削除して代わりにmysql-connector-python==8.2.0をインストールしています。

requirements.txt
alembic==1.13.1
annotated-types==0.6.0
boto3==1.4.8
botocore==1.8.11
certifi==2023.11.17
charset-normalizer==3.3.2
docutils==0.14
exceptiongroup==1.2.0
functions==0.7.0
greenlet==3.0.3
idna==3.6
iniconfig==2.0.0
jmespath==0.9.3
Mako==1.3.0
MarkupSafe==2.1.3
# mysqlclient==2.2.1
packaging==23.2
pluggy==1.3.0
pydantic==2.5.3
pydantic_core==2.14.6
pytest==7.4.4
python-dateutil==2.6.1
python-multipart==0.0.6
pytz==2023.3.post1
requests==2.31.0
s3transfer==0.1.12
schemas==0.7.1
six==1.11.0
SQLAlchemy==2.0.25
SQLAlchemy-Utils==0.41.1
tomli==2.0.1
typing_extensions==4.9.0
urllib3==2.1.0
xmltodict==0.13.0
mysql-connector-python==8.2.0

イメージをビルドします。

finch build -t test_distroless:1 .

サイズを確認するため、docker imagesを実行します。

finch images

実行結果は以下のとおりです。

test_alpine        1      d77ee33a7032    About a minute ago    linux/arm64    337.2 MiB    104.2 MiB
test_distroless    1      b2538550ade5    6 seconds ago         linux/arm64    147.1 MiB    41.3 MiB

サイズは147MBです。distrolessイメージを使うことでほぼ同じPythonのパッケージを使いつつ、イメージサイズを大幅に削減できました。

※dockerの時と比較すると10MB程度くらいですが、若干大きい気がします。

distrolessイメージを作るときのポイント

イメージサイズを削減できたところでdistrolessイメージを作るときのポイントを確認します。
主に以下のポイントです。

  • マルチステージビルドを使う
  • その他のパッケージに依存したパッケージをインストールしないもしくは代わりを用意する

それぞれ見ていきましょう。

マルチステージビルドを使う

dockerにはマルチステージビルドという機能があります。マルチステージビルドとは複数のFROMを使ってイメージを構築する機能です。

以下のようなメリットがあります。

  • ビルドキャッシュから必要なものをコピーすることでビルドの高速化
    • パッケージインストール時に発生するダウンロード時間をより短くできる

ただし、以下のようなデメリットもあります。

  • 特定のビルドイメージに依存してしまう
  • ビルドイメージを保存するため、相対的に保存データ容量が大きくなる

また、昨今においてはさまざまなアーキテクチャで開発を行うことが多くなってきているため
ビルドイメージを取得する際にアーキテクチャによってビルドイメージは異なることがあります。
ビルドイメージの構築はCI/CDなどを構築してクラウド上でやるのが良いでしょう。

その他のパッケージに依存したパッケージをインストールしない

distrolessイメージを使うときには、その他のパッケージに依存したパッケージをインストールしないようにする必要があります。

mysqlclientをインストールする場合は依存しているapkのパッケージをインストールする必要があります。
しかし、distrolessイメージにはシェルとパッケージシステムが存在しないため、apkのパッケージをインストールできません。

ちなみにmysqlclientをインストールしようとするとpkg-configが正常に動作せず、インストールに失敗します。

まとめ

今回は既存のコンテナイメージをdistrolessイメージを使って改善しました。
distrolessイメージを使うことでイメージサイズを大幅に削減できるため、使えるところでは使っていきたいです。

また、イメージをビルドする際はクラウドベースのビルド環境を構築しておきましょう。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?