マルチステージやwhlなどを使ってdockerのビルドサイズを小さくする

初めに

以下のRepositoryにて モデルをonnxおよぼortモデルに変換する処理をdockerで行っていますが、その際に github のcache & GitHub Actionsの処理の高速化のためにdocker imageをなるべく小さくしました。その際の行ったことを記載します

github.com

開発環境

  • (手元の動作確認およびサイズ確認 環境) Windows11

シンプルにimageを作る

まずは何も考えずにシンプルに以下の Dockerfileでビルドをします

# ベースイメージの指定(CPU版のPython 3.11)
FROM python:3.11-slim

# 必須のパッケージをインストール
RUN apt-get update && apt-get install -y \
    git \
    curl \
    && rm -rf /var/lib/apt/lists/*

# GitHub CLI のインストール
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | \
    dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \
    chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg && \
    echo "deb [arch=$(dpkg --print-architecture) \
    signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] \
    https://cli.github.com/packages stable main" > \
    /etc/apt/sources.list.d/github-cli.list && \
    apt-get update && apt-get install -y gh && \
    rm -rf /var/lib/apt/lists/*

# 作業ディレクトリを設定
WORKDIR /app

# リポジトリの内容をコピー
COPY . /app

# ライブラリのインストール
RUN python -m pip install --upgrade pip

# PyTorchのインストール(CPU版)
RUN pip install torch==2.1.0

# 他の依存関係をインストール
RUN pip install -r requirements.txt

# エントリーポイントを設定(オプション)
CMD ["bash"]

この際のサイズは以下の感じでした

docker images model-convert    
REPOSITORY      TAG       IMAGE ID       CREATED         SIZE
model-convert   latest    d27fec6e655e   6 minutes ago   10.6GB
docker history model-convert:latest
IMAGE          CREATED         CREATED BY                                       SIZE      COMMENT
d27fec6e655e   7 minutes ago   CMD ["bash"]                                     0B        buildkit.dockerfile.v0
<missing>      7 minutes ago   RUN /bin/sh -c rm -rf ~/.cache/pip # buildkit    0B        buildkit.dockerfile.v0
<missing>      7 minutes ago   RUN /bin/sh -c apt-get update && apt-get ins…   8.53MB    buildkit.dockerfile.v0
<missing>      7 minutes ago   COPY . /app # buildkit                           4.83GB    buildkit.dockerfile.v0
<missing>      7 minutes ago   COPY /usr/local/bin /usr/local/bin # buildkit    33.8kB    buildkit.dockerfile.v0
<missing>      7 minutes ago   COPY /usr/local/lib/python3.11/site-packages…   5.64GB    buildkit.dockerfile.v0
<missing>      34 hours ago    WORKDIR /app                                     0B        buildkit.dockerfile.v0
<missing>      2 weeks ago     CMD ["python3"]                                  0B        buildkit.dockerfile.v0
<missing>      2 weeks ago     RUN /bin/sh -c set -eux;  for src in idle3 p…   36B       buildkit.dockerfile.v0
<missing>      2 weeks ago     RUN /bin/sh -c set -eux;   savedAptMark="$(a…   45.8MB    buildkit.dockerfile.v0
<missing>      2 weeks ago     ENV PYTHON_SHA256=2a9920c7a0cd236de33644ed98…   0B        buildkit.dockerfile.v0
<missing>      2 weeks ago     ENV PYTHON_VERSION=3.11.11                       0B        buildkit.dockerfile.v0
<missing>      2 weeks ago     ENV GPG_KEY=A035C8C19219BA821ECEA86B64E628F8…   0B        buildkit.dockerfile.v0
<missing>      2 weeks ago     RUN /bin/sh -c set -eux;  apt-get update;  a…   8.48MB    buildkit.dockerfile.v0
<missing>      2 weeks ago     ENV LANG=C.UTF-8                                 0B        buildkit.dockerfile.v0
<missing>      2 weeks ago     ENV PATH=/usr/local/bin:/usr/local/sbin:/usr…   0B        buildkit.dockerfile.v0
<missing>      2 weeks ago     # debian.sh --arch 'amd64' out/ 'bookworm' '…   74.8MB    debuerreotype 0.15

dockerignoreの対応

dockerビルド時の必要なものだけをビルドコンテキストに含めます

以下のようなファイルを作成します

# バージョン管理システムのディレクトリを除外
.git
.gitignore

# Python キャッシュファイルを除外
__pycache__
*.py[cod]

# データや出力ファイルを除外
data/
outputs/
logs/
checkpoints/

# 大容量のモデルやファイルを除外
*.pt
*.pth
*.onnx

# その他不要なファイルやディレクトリ
node_modules/
tmp/

これによって不要なデータが含まれることがなくなりました

ビルド時に必要なファイルのみをコピーする

以下のように ビルド時に必要なファイルのみをコピーするようにします

# ビルドステージから必要なファイルをコピー
COPY --from=builder /usr/local /usr/local

# 必要なファイルのみをコピー
COPY process_issues.py ./

torchをwhlからインストールする

PyTorchがイメージサイズの大部分を占めている可能性が高いため、サイズの削減を試みます。 今回は pytorch(cpu) : 2.5.1を使いたかったので、以下を使用します

torch-2.5.1+cpu.cxx11.abi-cp311-cp311-linux_x86_64.whl

これらの一覧は以下から確認することができます

https://download.pytorch.org/whl/torch/

Dockerfile内でダウンロードおよびインストールを行って、不要になったwhlのファイルの削除を行います

RUN curl -L -o torch-2.5.1+cpu.cxx11.abi-cp311-cp311-linux_x86_64.whl \
    "https://download.pytorch.org/whl/cpu-cxx11-abi/torch-2.5.1%2Bcpu.cxx11.abi-cp311-cp311-linux_x86_64.whl" && \
    pip install --no-cache-dir torch-2.5.1+cpu.cxx11.abi-cp311-cp311-linux_x86_64.whl && \
    rm torch-2.5.1+cpu.cxx11.abi-cp311-cp311-linux_x86_64.whl

マルチステージでビルドを行う

以下のように 複数のステージにわけて 1stで必要なものをビルドして、2stにビルド情報を渡します

# ビルドステージ
FROM python:3.11-slim AS builder

.....

# ランタイムステージ
FROM python:3.11-slim

上記の対応を入れることで、1.38GBまで小さくすることができました

docker images model-convert        
REPOSITORY      TAG       IMAGE ID       CREATED         SIZE
model-convert   latest    2730c993208e   9 seconds ago   1.38GB
docker history model-convert:latest
IMAGE          CREATED          CREATED BY                                       SIZE      COMMENT
2730c993208e   13 seconds ago   CMD ["bash"]                                     0B        buildkit.dockerfile.v0
<missing>      13 seconds ago   RUN /bin/sh -c rm -rf /root/.cache/pip     &…   0B        buildkit.dockerfile.v0
<missing>      14 seconds ago   COPY process_issues.py ./ # buildkit             8.31kB    buildkit.dockerfile.v0
<missing>      14 seconds ago   COPY /usr/local /usr/local # buildkit            1.11GB    buildkit.dockerfile.v0
<missing>      16 minutes ago   WORKDIR /app                                     0B        buildkit.dockerfile.v0
<missing>      16 minutes ago   RUN /bin/sh -c curl -fsSL https://cli.github…   132MB     buildkit.dockerfile.v0
<missing>      18 minutes ago   RUN /bin/sh -c apt-get update && apt-get ins…   11.8MB    buildkit.dockerfile.v0
<missing>      2 weeks ago      CMD ["python3"]                                  0B        buildkit.dockerfile.v0
<missing>      2 weeks ago      RUN /bin/sh -c set -eux;  for src in idle3 p…   36B       buildkit.dockerfile.v0
<missing>      2 weeks ago      RUN /bin/sh -c set -eux;   savedAptMark="$(a…   45.8MB    buildkit.dockerfile.v0
<missing>      2 weeks ago      ENV PYTHON_SHA256=2a9920c7a0cd236de33644ed98…   0B        buildkit.dockerfile.v0
<missing>      2 weeks ago      ENV PYTHON_VERSION=3.11.11                       0B        buildkit.dockerfile.v0
<missing>      2 weeks ago      ENV GPG_KEY=A035C8C19219BA821ECEA86B64E628F8…   0B        buildkit.dockerfile.v0
<missing>      2 weeks ago      RUN /bin/sh -c set -eux;  apt-get update;  a…   8.48MB    buildkit.dockerfile.v0
<missing>      2 weeks ago      ENV LANG=C.UTF-8                                 0B        buildkit.dockerfile.v0
<missing>      2 weeks ago      ENV PATH=/usr/local/bin:/usr/local/sbin:/usr…   0B        buildkit.dockerfile.v0
<missing>      2 weeks ago      # debian.sh --arch 'amd64' out/ 'bookworm' '…   74.8MB    debuerreotype 0.15