OpenCV Docker多级生成-无法安装预生成源代码

OpenCV Docker多级生成-无法安装预生成源代码,docker,opencv,cmake,Docker,Opencv,Cmake,我正在尝试构建一个Docker映像,其中包含一个非常特殊的OpenCV配置,支持CUDA和GPU 构建成功,如果我从构建映像的同一上下文中安装它,那么它就可以正常工作 当我尝试使用多阶段构建时会出现问题,以避免保留构建OpenCV所需的所有依赖项。在继续阅读之前,如果您对如何在Docker多级构建中复制OpenCV构建工件(包括Python绑定!)有更好的解决方案,那么接下来的问题实际上可能是XY问题,这是我的实际意图 现在谈谈我尝试的解决方案和我的斗争: 我运行了COPY--from=requ

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

构建成功,如果我从构建映像的同一上下文中安装它,那么它就可以正常工作

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

现在谈谈我尝试的解决方案和我的斗争:

我运行了
COPY--from=requirements/opencv/opencv
,它可以正常工作,而且它显然可以按照正确的路径复制所有内容(我检查了文件系统)。但是,当我从
build
文件夹
makeinstall
运行时,会出现以下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\u opencv.sh
脚本具有以下选项:

#/bin/bash
cmake-D cmake\u BUILD\u TYPE=发布\
-D CMAKE_C_编译器=/usr/bin/gcc-8\
-D CMAKE_INSTALL_前缀=/usr/local\
-D INSTALL_PYTHON_EXAMPLES=OFF\
-D安装\u C\u示例=关闭\
-D且_TBB=开启\
-D且_CUDA=开启\
-D BUILD_opencv_cudacodec=OFF\
-D启用\u快速\u数学=1\
-D CUDA_FAST_MATH=1\
-D与_CUBLAS=1\
-_V4L=ON时的D\
-带_QT=关闭的D\
-D与_OPENGL=ON\
-D且_GSTREAMER=ON\
-D OPENCV_GENERATE_PKGCONFIG=ON\
-D OPENCV_PC_FILE_NAME=OPENCV.PC\
-D OPENCV_ENABLE_NONFREE=ON\
-D OPENCV_PYTHON3_安装_路径=$SITE\u包\
-D OPENCV_额外模块_路径=$EXTRA_模块\
-D PYTHON_可执行文件=/usr/bin/python3\
-D且_CUDNN=ON\
-D OPENCV_DNN_CUDA=ON\
-D CUDA_ARCH_BIN=$CUDA_ARCH\
-D CUDA_TOOLKIT_ROOT_DIR=/usr/local/CUDA-10.2\
-D带_GTK_2_X=关闭\
-D BUILD_EXAMPLES=OFF。。
make-j16
requirements.txt
文件中至少需要
numpy

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

- docker
    - Dockerfile
    - build_opencv.sh
- requirements.txt
从生成上下文的根使用生成:

docker build -t opencvmultistage:latest -f docker/Dockerfile .
我做错什么了吗?也许CMake有一些奇怪的缓存,我没有复制到新映像,导致构建失败


为了清楚起见,如果我在
build\u opencv.sh
脚本中添加
make install
,它可以工作,但是我在构建上下文中安装了opencv,而不是在运行时,这不是我假装要做的
makeinstall
运行在同一个目录中,并且应该存在相同的文件,因此我不知道发生了什么。

在同一阶段运行
cmake&make
makeinstall
,然后复制安装文件夹更简单。它将允许在最终docker映像中没有任何构建工具,如
cmake
build-essential

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

修改生成脚本以使用自定义的
CMAKE\u INSTALL\u前缀

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

  • 要在阶段1中运行
    makeinstall

    # 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阶段复制安装

    # 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
    

  • 谢谢我考虑过这一点,但我担心的是,正如您所提到的,/usr/local会有冲突,并且会增加开发依赖项的大小。但CMAKE_安装_前缀建议很好,我会检查一下并回复。复制/usr/local有点太多,它会复制/usr/local/cuda,并会增加图像大小,最好复制所需的文件夹。