OpenCV Docker多阶段构建-无法安装预构建的源代码

时间:2020-08-26 06:58:29

标签: docker opencv cmake

我正在尝试构建一个Docker映像,其中包括具有CUDA和GPU支持的OpenCV的非常特殊的配置。

构建成功,并且如果我从构建映像的同一上下文中make install进行构建,那么它将毫无问题。

当我尝试使用多阶段构建时,会发生问题,以避免保留构建OpenCV所需的所有依赖关系。在继续阅读之前,如果您对如何在Docker多阶段构建中复制OpenCV构建工件(包括Python绑定!)有更好的解决方案,那么以下内容实际上可能是XY问题,这是我的实际情况意向。

现在为我尝试的解决方案和我所经历的挣扎:

我运行COPY --from=requirements /opencv /opencv,它可以正常工作,并且显然可以将所有内容复制到正确的路径中(我检查了文件系统)。但是,当我从build文件夹make install运行时,出现此CMake错误:

CMake Error: The source directory "" does not exist.
Specify --help for usage, or press the help button on the CMake GUI.
Makefile:2724: recipe for target 'cmake_check_build_system' failed
make: *** [cmake_check_build_system] Error 1

同样,来自相同文件夹但没有多级构建的相同命令有效。

这是我的Dockerfile

# Stage 1: Build
FROM nvidia/cuda:10.2-cudnn7-devel-ubuntu18.04 AS requirements
# Install dependencies
RUN echo "deb http://es.archive.ubuntu.com/ubuntu eoan main universe" | tee -a  /etc/apt/sources.list
RUN apt-get update && apt-get -y upgrade
RUN apt-get -y install build-essential cmake unzip pkg-config libjpeg-dev libpng-dev libtiff-dev libavcodec-dev \
                    libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev libgtk-3-dev libatlas-base-dev \
                    gfortran python3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libxvidcore-dev x264 \
                    libx264-dev libfaac-dev libmp3lame-dev libtheora-dev libfaac-dev libmp3lame-dev libvorbis-dev \
                    libjpeg-dev libpng-dev libtiff-dev git python3-pip libtbb-dev libprotobuf-dev protobuf-compiler \
                    libgoogle-glog-dev libgflags-dev libgphoto2-dev libeigen3-dev libhdf5-dev wget libtbb-dev gcc-8 g++-8 llvm \
                    python3-venv libgirepository1.0-dev
# Install my project requirements
WORKDIR /venv
RUN python3 -m venv /venv
ENV PATH="/venv/bin:$PATH"
ADD requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
# Build OpenCV
WORKDIR /opencv
RUN wget https://github.com/opencv/opencv/archive/4.4.0.zip && mv 4.4.0.zip opencv.zip && unzip opencv.zip && rm opencv.zip
RUN wget https://github.com/opencv/opencv_contrib/archive/4.4.0.zip && mv 4.4.0.zip opencv_contrib.zip && unzip opencv_contrib.zip && rm opencv_contrib.zip
WORKDIR /opencv/opencv-4.4.0/build
ENV SITE_PACKAGES /venv/lib/python3.7/site-packages
ENV EXTRA_MODULES /opencv/opencv_contrib-4.4.0/modules
ENV CUDA_ARCH 7.5
ADD docker/build_opencv.sh .
RUN ./build_opencv.sh
# Stage 2: runtime
FROM nvidia/cuda:10.2-cudnn7-runtime-ubuntu18.04
RUN apt-get update && apt-get -y upgrade
RUN apt-get -y install build-essential cmake python3-venv
# Install OpenCV
COPY --from=requirements /opencv /opencv
WORKDIR /opencv/opencv-4.4.0/build
RUN make install && ldconfig
# build fails here and the rest is specific to my project so I've ommitted it

build_opencv.sh脚本具有以下选项:

#!/bin/bash
cmake -D CMAKE_BUILD_TYPE=RELEASE \
                -D CMAKE_C_COMPILER=/usr/bin/gcc-8 \
                -D CMAKE_INSTALL_PREFIX=/usr/local \
                -D INSTALL_PYTHON_EXAMPLES=OFF \
                -D INSTALL_C_EXAMPLES=OFF \
                -D WITH_TBB=ON \
                -D WITH_CUDA=ON \
                -D BUILD_opencv_cudacodec=OFF \
                -D ENABLE_FAST_MATH=1 \
                -D CUDA_FAST_MATH=1 \
                -D WITH_CUBLAS=1 \
                -D WITH_V4L=ON \
                -D WITH_QT=OFF \
                -D WITH_OPENGL=ON \
                -D WITH_GSTREAMER=ON \
                -D OPENCV_GENERATE_PKGCONFIG=ON \
                -D OPENCV_PC_FILE_NAME=opencv.pc \
                -D OPENCV_ENABLE_NONFREE=ON \
                -D OPENCV_PYTHON3_INSTALL_PATH=$SITE_PACKAGES \
                -D OPENCV_EXTRA_MODULES_PATH=$EXTRA_MODULES \
                -D PYTHON_EXECUTABLE=/usr/bin/python3 \
                -D WITH_CUDNN=ON \
                -D OPENCV_DNN_CUDA=ON \
                -D CUDA_ARCH_BIN=$CUDA_ARCH \
                -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-10.2  \
                -D WITH_GTK_2_X=OFF \
                -D BUILD_EXAMPLES=OFF ..
make -j16

您的numpy文件中至少需要requirements.txt

为了重现该问题,最小的设置应具有以下结构:

- docker
    - Dockerfile
    - build_opencv.sh
- requirements.txt

从构建上下文的根目录使用构建:

docker build -t opencvmultistage:latest -f docker/Dockerfile .

我做错什么了吗?也许CMake有一些奇怪的缓存,我没有将其复制到新映像,并且使构建失败了?

为清楚起见,如果我在make install脚本中添加build_opencv.sh可以正常工作,但是我在构建上下文中而不是运行时中安装了OpenCV,这不是我的假装。 make install在同一目录中运行,并且应该存在相同的文件,所以我真的不知道发生了什么。

1 个答案:

答案 0 :(得分:2)

在同一阶段运行cmake & makemake install然后复制安装文件夹更为简单。最终的Docker映像中将不允许使用任何cmakebuild-essential之类的构建工具。

我们将使用自定义CMAKE_INSTALL_PREFIX,以便将OpenCV二进制文件安装到目录中,然后可以将其直接复制到下一个阶段。使用自定义前缀将避免不必复制不再需要的CUDA安装或开发库。然后,我们将在该目录上运行ldconfig以照常链接库。

修改构建脚本以使用自定义CMAKE_INSTALL_PREFIX

mkdir /prefix
cmake -D CMAKE_BUILD_TYPE=RELEASE \
# all compiler flags...
-D CMAKE_INSTALL_PREFIX=/prefix

修改Dockerfile

  1. 在阶段1运行make install

    # Stage 1: Build
    FROM nvidia/cuda:10.2-cudnn7-devel-ubuntu18.04 AS requirements
    ...
    ADD build_opencv.sh .
    RUN ./build_opencv.sh && make install
    
  2. 在第2阶段复制安装

    # Stage 2: runtime
    FROM nvidia/cuda:10.2-cudnn7-runtime-ubuntu18.04
    RUN apt-get update && apt-get -y upgrade
    RUN apt-get -y install build-essential python3-venv
    # Install OpenCV
    COPY --from=requirements /prefix /prefix
    COPY --from=requirements /venv /venv
    ENV PATH="/venv/bin:$PATH"
    RUN ldconfig /prefix