この記事について
シンプルなPythonのDockerイメージを軽量化する方法について調べると,ベースイメージをslimにする,マルチステージビルドをするといった方法をよく見かけます.しかし,DjangoでMySQLを使用する場合の推奨ドライバであるmysqlclientをインストールするためには,少し工夫が必要みたいです.
そこで,イメージを限りなく軽量化しつつ,mysqlclientがインストールできるDockerfileを作成してみました.
準備
今回は日本語訳されたDocker公式ドキュメントのクイックスタートにあるDockerfileを編集して軽量化していきます.
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
ちなみにrequirements.txtには必要最低限のものだけ記述してます.
Django
mysqlclient
まずはこのDockerfileを使ってイメージをビルドしてみます.(この後の比較のためにタグつけてます)
$ docker build . -t django-mysqlclient:base
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
django-mysqlclient base 1.07GB
1.07 GBというサイズになりました.こいつをどこまで軽量化できるか試していきます.
軽量化する
slimイメージを使う
まずはベースイメージをslimに変更してみます.
slimイメージを使用することで,よく用いられるライブラリ以外を除外した,サイズが削減されたPythonイメージをpullできるようです.しかし,mysqlclientのインストール時に必要なパッケージも除外されるようで,apt-getでインストールしています.
+ FROM python:3-slim
- FROM python:3
ENV PYTHONUNBUFFERED 1
+ RUN apt-get update && \
+ apt-get install -y default-libmysqlclient-dev build-essential pkg-config
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
このDockerfileを使ってイメージをビルドしてみます.
$ docker build . -t django-mysqlclient:slim
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
django-mysqlclient base 1.07GB
django-mysqlclient slim 546MB
1.07 GB から 546 MB になりました.だいたい半分のサイズですね.
マルチステージビルドする
次にマルチステージビルドを行います.
マルチステージビルドとは,ビルドに必要なパッケージを含むイメージと,実行に必要なパッケージだけを含むイメージを別々にビルドすることで,最終的なイメージを軽量化する手法です.
FROM python:3-slim as base
FROM base as builder
ENV PYTHONUNBUFFERED 1
RUN apt-get update && \
apt-get install -y default-libmysqlclient-dev build-essential pkg-config
RUN mkdir /install
ADD requirements.txt .
RUN pip install --prefix=/install -r requirements.txt
FROM base as runner
ENV PYTHONUNBUFFERED 1
COPY --from=builder /install /usr/local
COPY --from=builder /usr/lib/x86_64-linux-gnu/libmysql* /usr/lib/x86_64-linux-gnu
COPY --from=builder /usr/lib/x86_64-linux-gnu/libmaria* /usr/lib/x86_64-linux-gnu
COPY --from=builder /usr/bin/mysql_config /usr/bin
RUN mkdir /code
WORKDIR /code
ADD . /code/
簡単に解説をすると,builderステージではこれまでの同様にapt-getやpipで必要なパッケージをインストールしておき,runnerステージでDjangoとmysqlclientの動作に必要なファイルのみをコピーしてきています.
さて,このDockerfileを使ってイメージをビルドしてみます.
platformによってmysqlclient関連のパッケージがインストールされる場所が変わるようで,M1/M2 Macの方は
--platform=linux/amd64
オプションを追加すると動作するかと思われます.
$ docker build . -t django-mysqlclient:slim-multi
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
django-mysqlclient base 1.07GB
django-mysqlclient slim 546MB
django-mysqlclient slim-multi 156MB
546 MB から 156 MB になりました.最初と比べると約1/7のサイズになりましたね.
おわりに
今回はクイックスタートのDockerfileを比較対象にするために,最低限の変更にとどめていますが,もっと最適化ができる部分(ADD
命令をCOPY
命令にするとか)があるかと思います.間違い・改善点等があれば指摘していただけますと幸いです.
参考