使用Docker BuildKit编译OpenCV失败:无法找到指定图片文件
问题描述
我有一个长期用于编译OpenCV的Dockerfile,近期尝试使用BuildKit进行交叉编译时,编译失败并报错:RCC无法找到'/opencv/modules/highgui/src/window_QT.qrc'中引用的'files_Qt/Milky/48/28.png'。我验证过该文件确实存在,且在容器交互式shell中手动编译可成功。请问BuildKit的工作机制是否会对编译过程产生影响?
构建命令
DOCKER_BUILDKIT=1 docker build --no-cache --progress=plain -t "buildkit_error:latest" -f Dockerfile .
Dockerfile示例
FROM ubuntu:20.04 WORKDIR / # Setup apt repositories RUN \ apt update && \ apt install -y --no-install-recommends \ wget \ software-properties-common && \ add-apt-repository ppa:deadsnakes/ppa && \ apt install -y --fix-broken && \ apt update && \ apt upgrade -y && \ apt dist-upgrade -y && \ apt remove -y python3 && \ apt clean && \ apt autoremove -y && \ apt autoclean -y # Install apt packages # ORDER ALPHABETICALLY! RUN \ apt install -y --no-install-recommends \ build-essential \ clang-10 \ cmake \ cpio \ git \ libdrm-dev \ libcairo2-dev \ libomp-10-dev \ llvm-10-dev \ openssh-client \ pkg-config \ python3.6-dev \ python3.6-distutils\ python3.6-minimal \ python3-pip \ qt5-default # Install pip dependencies # ORDER ALPHABETICALLY! RUN python3.6 -m pip install --no-cache-dir \ numpy==1.16.1 \ setuptools==59.6.0 \ wheel==0.37.1 RUN \ ln -sf /usr/bin/python3.6 /usr/bin/python3 && \ ln -sf /usr/bin/python3 /usr/bin/python ENV opencv=3.4.3 RUN git clone --branch $opencv --depth 1 https://github.com/opencv/opencv.git RUN ls -al /opencv/modules/highgui/src/files_Qt/Milky/48 # build opencv from source RUN \ mkdir opencv/build && cd opencv/build && cmake -DBUILD_TIFF=ON \ -DCMAKE_C_COMPILER=clang-10 \ -DCMAKE_CXX_COMPILER=clang++-10 \ -DENABLE_FAST_MATH=ON \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_opencv_java=OFF \ -DWITH_CUDA=OFF \ -DENABLE_CXX11=ON \ -DWITH_OPENGL=ON \ -DWITH_OPENCL=ON \ -DWITH_IPP=ON \ -DWITH_TBB=ON \ -DWITH_EIGEN=ON \ -DWITH_V4L=OFF \ -DWITH_GTK=ON \ -DWITH_GTK_2_X=ON \ -DBUILD_PERF_TESTS=OFF \ -DBUILD_opencv_apps=OFF \ -DBUILD_JAVA=OFF \ -DBUILD_PROTOBUF=OFF \ -DBUILD_PACKAGE=OFF \ -DBUILD_TESTS=OFF \ -DBUILD_opencv=OFF \ -DBUILD_opencv_dnn=OFF \ -DBUILD_opencv_java_bindings_generator=OFF \ -DBUILD_opencv_shape=OFF \ -DBUILD_opencv_stitching=OFF \ -DBUILD_opencv_superres=OFF \ -DBUILD_opencv_ts=OFF \ -DBUILD_opencv_video=OFF \ -DBUILD_opencv_videoio=OFF \ -DBUILD_opencv_videostab=OFF \ -DBUILD_opencv_world=OFF \ -DBUILD_opencv_ml=OFF \ -DBUILD_opencv_photo=OFF \ -DWITH_1394=OFF \ -DWITH_FFMPEG=OFF \ -DWITH_GSTREAMER=OFF \ -DWITH_IMGCODEC_HDR=OFF \ -DWITH_IMGCODEC_PXM=OFF \ -DWITH_IMGCODEC_SUNRASTER=OFF \ -DWITH_JASPER=OFF \ -DWITH_OPENCVAMDBLAS=OFF \ -DWITH_OPENCVAMDFFT=OFF \ -DWITH_OPENEXR=OFF \ -DWITH_OPENNI=OFF \ -DWITH_OPENNI2=OFF \ -DWITH_OPENVX=OFF \ -DWITH_VTK=OFF \ -DWITH_V4L=OFF \ -DWITH_QUIRC=OFF \ -DWITH_QT=ON \ -DBUILD_opencv_calib3d=ON \ -DBUILD_opencv_core=ON \ -DBUILD_opencv_python3=ON \ -DBUILD_opencv_flann=ON \ -DBUILD_opencv_python_binding_generator=ON \ -DBUILD_opencv_highgui=ON \ -DBUILD_opencv_imgcodecs=ON \ -DBUILD_opencv_features2d=ON \ -DBUILD_opencv_imgproc=ON \ -DWITH_OPENMP=ON \ -DWITH_PNG=ON \ -DWITH_HALIDE=OFF .. && \ make -j6 && make install
问题分析与解决方案
BuildKit的工作机制确实可能引发这个问题,核心原因在于它的并行构建特性和文件系统处理逻辑和传统Docker构建存在差异:
并行构建的依赖误判
BuildKit会自动分析RUN指令间的依赖关系,尝试并行执行无依赖步骤。即便你的git clone和make是串行编写,BuildKit的文件系统快照处理可能导致Qt的RCC工具在读取资源文件时,无法正确识别刚克隆完成的文件(即使RUN ls已确认文件存在)。相对路径解析的环境差异
Qt的RCC工具处理.qrc文件时依赖相对路径查找资源。在BuildKit的隔离构建环境中,工具的工作目录或上下文路径可能和交互式shell中不一致,导致相对路径解析失败。
可行解决办法
- 强制串行构建:在Dockerfile开头添加
# syntax=docker/dockerfile:1.4(指定BuildKit兼容语法),或者构建时设置BUILDKIT_CONTEXT_KEEP_GIT_DIR=1环境变量,确保Git克隆的目录结构完整,避免快照处理干扰。 - 明确指定RCC工具路径:在cmake命令中添加
-DCMAKE_RCC_COMPILER=/usr/bin/rcc,同时添加-DCMAKE_RCC_FLAGS="-v"输出详细日志,排查路径解析问题。 - 固定工作目录:将编译步骤的工作目录明确设置为
/opencv/build,避免路径混乱:WORKDIR /opencv/build RUN cmake [你的参数] .. && make -j6 && make install - 临时禁用BuildKit:去掉构建命令中的
DOCKER_BUILDKIT=1,确认是否为BuildKit导致的问题,再逐步排查优化点。
另外,可以在RUN ls -al之后添加RUN cat /opencv/modules/highgui/src/window_QT.qrc,确认qrc文件中的资源路径是否是相对于自身所在目录的有效路径。
内容的提问来源于stack exchange,提问作者Matthias Verstraete
相关产品推荐
相关产品推荐

