Python の OpenCV で GStreamer を使う場合、自前でビルドする必要があり、そのための Dockerfile を以前作成しました。
その時の記事が以下です。
ただ、これで作成した Docker イメージのサイズが 2.5GB くらいあり、もっとサイズを小さくできないかなと考えていました。
その過程でマルチステージビルドというものを知ったのですが、OpenCV のビルドの成果物をどうやって最後のステージに持ってきたらよいか分からず悩んでいたら、以下のページを見つけました。
- https://github.com/NVIDIA/nvidia-docker/issues/806
- https://github.com/NVIDIA/gpu-rest-engine/blob/master/Dockerfile.caffe_server#L26-L41
- https://stackoverflow.com/questions/63592138/opencv-docker-multistage-build-cannot-install-prebuilt-source
ビルドステージでは、make install
の後、ldconfig
で共有リンクを作成しています。
リリースステージでは /usr/local/lib
以下を全てコピーし、ldconfig
で共有リンクを作成しています。
というわけで、これを参考にマルチステージビルドを行ってみました。
ただ、私の場合、/usr/local/lib
のコピーだけでは依存パッケージが不足していて動かなかったので、/usr/lib
と /usr/share
の中身も全部コピーしたら動くようになりました。
COPY --from=build /usr/lib /usr/lib
COPY --from=build /usr/share /usr/share
COPY --from=build /usr/local/lib /usr/local/lib
RUN ldconfig
以上で、イメージサイズを 1.9GB まで減らせました。
ここらへん、本当に依存しているパッケージだけをコピーするようにできれば、まだまだサイズを小さくできそうではあります。
以下、Dockerfile のサンプルです。
# Stage1: build
FROM ubuntu:20.04 as build
# tzdataのタイムゾーン入力を求められないようにする
# https://tmyoda.hatenablog.com/entry/20210124/1611416396
ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt update && \
apt install -y --no-install-recommends \
software-properties-common && \
update-ca-certificates && \
# 必要なパッケージをインストール
apt install -y \
python3-pip \
libgl1-mesa-dev \
libsm6 \
git \
wget \
unzip \
# OpenCV: Required build dependencies
# https://docs.opencv.org/4.x/d2/de6/tutorial_py_setup_in_ubuntu.html
cmake \
python3-dev \
python3-numpy \
libavcodec-dev \
libavformat-dev \
libswscale-dev \
libgtk2.0-dev \
libgtk-3-dev \
# OpenCV: Optional Dependencies
libpng-dev \
libjpeg-dev \
libopenexr-dev \
libtiff-dev \
libwebp-dev \
# OpenCV のビルド時に -D WITH_QT=ON を設定するために以下が必要だった
qtbase5-dev \
qtdeclarative5-dev \
# gstreamer のインストール
# https://gstreamer.freedesktop.org/documentation/installing/on-linux.html
libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev \
libgstreamer-plugins-bad1.0-dev \
gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav \
gstreamer1.0-doc \
gstreamer1.0-tools \
gstreamer1.0-x \
gstreamer1.0-alsa \
gstreamer1.0-gl \
gstreamer1.0-gtk3 \
gstreamer1.0-qt5 \
gstreamer1.0-pulseaudio && \
# aptのクリア
apt autoremove && apt clean && rm -rf /var/lib/apt/lists/*
# OpenCV のビルドとインストール
# https://docs.opencv.org/master/d2/de6/tutorial_py_setup_in_ubuntu.html
# https://toriten1024.hatenablog.com/entry/2018/09/29/012205
# https://dlrecord.hatenablog.com/entry/2017/12/15/145356
# https://atmarkit.itmedia.co.jp/ait/articles/1704/10/news134.html
RUN mkdir opencv && \
cd /opencv && \
# OpenCV のダウンロード
wget https://github.com/opencv/opencv/archive/4.5.3.zip --no-check-certificate && \
unzip 4.5.3.zip && \
# OpenCV の cmake
cd /opencv/opencv-4.5.3 && \
mkdir build && \
cd /opencv/opencv-4.5.3/build && \
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D BUILD_DOCS=OFF \
-D BUILD_EXAMPLES=OFF \
-D BUILD_TESTS=OFF \
-D WITH_1394=OFF \
-D WITH_GSTREAMER=ON \
-D WITH_FFMPEG=ON \
# cv2.waitKey() を使うためには WITH_QT=ON にする必要があった
-D WITH_QT=ON \
.. && \
# OpenCV のビルド ※ $(nproc) はコア数を返す、make を並列処理させて高速化したい場合は指定する
#make -j${nproc} && \
#make -j2 && \
make && \
make install && \
ldconfig && \
# 後始末
rm -rf /opencv
# Stage2: release
FROM ubuntu:20.04
# tzdataのタイムゾーン入力を求められないようにする
# https://tmyoda.hatenablog.com/entry/20210124/1611416396
ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt update && \
# 必要なパッケージをインストール
apt install -y --no-install-recommends \
python3-pip \
python3-numpy \
# aptのクリア
&& \
apt autoremove && apt clean && rm -rf /var/lib/apt/lists/*
# Copy binary and dependencies
COPY --from=build /usr/lib /usr/lib
COPY --from=build /usr/share /usr/share
COPY --from=build /usr/local/lib /usr/local/lib
RUN ldconfig
# 必要なプラグインをインストール
RUN pip3 install \
aiohttp \
rich \
ruamel.yaml \
pymongo==3.12.0 \
influxdb \
flask \
flask-cors \
pytest \
pytest-mock \
mongomock \
websockets \
--trusted-host pypi.org \
--trusted-host files.pythonhosted.org
# bash起動
CMD [ "/bin/bash" ]