Orin开发套件11-从头创建Jetson的容器(2)

本系列文章的目的就是为大家解开这些变量的意义,让读者能清楚识别出这些变量之间的关系,提升对Dockerfile配置文件的了解,最终协助读者进一步简化出自己所需要的特定脚本与配置内容,以自己创建Docker镜像的能力。

前一篇文章已经对Jetson-container的容器创建脚本进行较为深入的说明,主要是为了更广泛地适用于不同JetPack版本的环境,因此使用嵌套式脚本的处理方式,初看之下会觉得相当繁琐,不过只要将脚本之间负责传递信息的变量内容理清,就会有种豁然开朗的感觉,并不难懂。

本文将继续深入Dockerfile这个镜像创建过程中最重要的配置文件内容,这样对整个容器镜像的创建就能了解地更加透彻。

  1. 使用docker_build.sh脚本创建容器:

scripst/docker_build_ml.sh里有三处调用scripst/docker_build.sh脚本的部分,才是真正创建个别容器的环节。

以创建l4t-pytorchbuild_pytorch()函数为例,在第26行调用docker_build.sh脚本并提供所有需要的相关参数:

26

27

28

29

30

31

32

33

34

sh ./scripts/docker_build.sh $pytorch_tag Dockerfile.pytorch \

                  --build-arg BASE_IMAGE=$BASE_IMAGE \

                  --build-arg PYTORCH_URL=$pytorch_url \

                  --build-arg PYTORCH_WHL=$pytorch_whl \

                  --build-arg TORCHVISION_VERSION=$vision_version \

                  --build-arg TORCHAUDIO_VERSION=$audio_version \

                  --build-arg TORCH_CUDA_ARCH_LIST=$cuda_arch_list \

                  --build-arg OPENCV_URL=$OPENCV_URL \

                  --build-arg OPENCV_DEB=$OPENCV_DEB

再看看docker_build.sh内容,里面里其实只有“docker build -t $CONTAINER -f $DOCKERFILE "$@" .”这一道创建镜像的指令,而相关所需要的参数都在上图中做好完整的配置。

这里调用了主目录下的Dockerfile.pytorch,并且以“--build-arg”方式将相关参数去对应Dockerfile.pytorch配置文件里的变量,这些变量在Dockerfile里可能会提供预设值,但是这些新的设定值就会覆盖掉配置文件的预设值。

创建l4t-tensorflow镜像的方式也是一样的,在第172buidl_tensorflow()函数里第181~187行内容(如下),也是调用docker_build.sh脚本去执行,不过配置文件改成Dockerfile.tensorflow,其他需要的参数也有所调整。

181

182

183

184

185

186

187

sh ./scripts/docker_build.sh $tensorflow_tag Dockerfile.tensorflow \

         --build-arg BASE_IMAGE=$BASE_IMAGE \

         --build-arg TENSORFLOW_URL=$tensorflow_url \

         --build-arg TENSORFLOW_WHL=$tensorflow_whl \

         --build-arg PROTOBUF_VERSION=$protobuf_version \

         --build-arg OPENCV_URL=$OPENCV_URL \

         --build-arg OPENCV_DEB=$OPENCV_DEB

在第275~281行用同样的模式去创建l4t-ml镜像,同样调用docker_build.sh脚本,不过配置文件换成Dockerfile.ml,相关配套参数也要根据配置文件内的实际状况进行调整,这里就不重复说明。

  1. 分析Dockerfile内容:

这个项目所提供的脚本,主要功能是为将对应的Dockerfile进行变量配置的工作,现在以创建l4t-ml镜像会使用到的Dockerfile.pytorchDockerfile.tensorflowDockerfile.ml为例,简单说明一下几个环节:

  1. 检查Dockerfile的变量

可以用文字编辑器打开这些文件,使用“搜索”功能查找关键字“ARG”,就能轻松找到里面的各项变量与预设值。

下面列出Dockerfile.pytorch6个变量与预设值:

21

54

55

65

66

132

ARG BASE_IMAGE=nvcr.io/nvidia/l4t-base:r32.4.4

ARG PYTORCH_URL=https://nvidia.box.com/shared/static/xxx.whl

ARG PYTORCH_WHL=torch-1.2.0-cp36-cp36m-linux_aarch64.whl

ARG TORCHVISION_VERSION=v0.4.0

ARG TORCH_CUDA_ARCH_LIST="5.3;6.2;7.2;8.7"

ARG TORCHAUDIO_VERSION

下面列出Dockerfile.tensorflow9个变量与预设值:

21

29

30

69

70

71

72

118

119

ARG BASE_IMAGE

ARG HDF5_DIR="/usr/lib/aarch64-linux-gnu/hdf5/serial/"

ARG MAKEFLAGS=-j$(nproc)

ARG PROTOBUF_VERSION=3.19.4

ARG PROTOBUF_URL=https://。。。/v${PROTOBUF_VERSION}

ARG PROTOBUF_DIR=protobuf-python-${PROTOBUF_VERSION}

ARG PROTOC_DIR=protoc-${PROTOBUF_VERSION}-linux-aarch_64

ARG TENSORFLOW_URL=https://。。。/。。。-linux_aarch64.whl

ARG TENSORFLOW_WHL=tensorflow-1.15.3+nv20.9-cp36-cp36m-linux_aarch64.whl

下面列出Dockerfile.ml10个变量与预设值:

21

22

23

39

40

116

117

138

139

ARG BASE_IMAGE=nvcr.io/nvidia/l4t-base:r32.4.4

ARG PYTORCH_IMAGE

ARG TENSORFLOW_IMAGE

ARG MAKEFLAGS=-j$(nproc)

ARG PYTHON3_VERSION=3.8

ARG CUPY_VERSION=v10.2.0

ARG CUPY_NVCC_GENERATE_CODE="arch=compute_53。。。"

ARG OPENCV_URL=https://nvidia.box.com/shared/static/。。。.gz

ARG OPENCV_DEB=OpenCV-4.5.0-aarch64.tar.gz

对照一下前面脚本所提供的参数,这样就能很轻松地了解前面脚本的任务与目的,如果前面脚本中有使用“--build-arg”设定的参数值,就会覆盖配置文件内的预设值。

  1. 导入所需要的基础镜像

这种docker build创建容器的方式,是必须基于某个(些)已经存在的基础容器之上,添加的相关依赖库与软件,因此首要工作就是从FROM  ${BASE_IMAGE}导入指定的基础镜像开始,在Dockerfile.pytorchDockerfile.tensorflow就是如此,不过在Dockerfile.ml文件中还多了以下两行内容:

25

26

FROM ${PYTORCH_IMAGE} as pytorch

FROM ${TENSORFLOW_IMAGE} as tensorflow

就是要从这两个镜像里提取PyTorchTensorflow的配套资源,如下所列的指令:

86

87

88

95

 

96

 

98

 

99

COPY --from=tensorflow /usr/local/bin/protoc /usr/local/bin

COPY --from=tensorflow /usr/local/lib/libproto* /usr/local/lib/

COPY --from=tensorflow /usr/local/include/google /usr/local/include/google

COPY --from=pytorch /usr/local/lib/python2.7/dist-packages/ /usr/local/lib/python2.7/dist-packages/

COPY --from=pytorch /usr/local/lib/python${PYTHON3_VERSION}/dist-packages/ /usr/local/lib/python${PYTHON3_VERSION}/dist-packages/

COPY --from=tensorflow /usr/local/lib/python2.7/dist-packages/ /usr/local/lib/python2.7/dist-packages/

COPY --from=tensorflow /usr/local/lib/python${PYTHON3_VERSION}/dist-packages/ /usr/local/lib/python${PYTHON3_VERSION}/dist-packages/

这是比较有技巧的安排,然后使用者可以独立创建l4t-pytorchl4t-tensorflow镜像,也可以将这两个框架合并在l4t-ml镜像内,此时只要将前面两个镜像已经编译安装好的部分复制到新镜像里面里就可以。

我们当然也可以将Dockerfile.pytorchDockerfile.tensorflow里的安装步骤全部放入Dockerfile.ml里面,不过这样会让整个配置文件变得非常冗长,估计要超过400行的内容,其最大的麻烦之处是会导致除错工作变得相当复杂与冗长,因此这里将处理过程进行分割再做合并。

  1. 安装依赖库

Dockerfile配置文件内使用“RUN”指定后面要执行的指令,后面加上Ubuntu使用的apt-get installpip install等方式安装依赖库或软件。由于镜像的操作是设定为root用户,因此不需要使用"sudo"去取得执行权限。

这个环节的最大困难点是要安装那些内容?这就需要整理出软件原厂所提供的依赖库列表,这个过程是相对繁琐的,而Jetson-containers项目所提供的12Dockerfile参考内容,能让我们节省很多摸索的时间。

  1. 需要编译的部分:

例如在Dockerfile.pytorch里面执行torchvision的编译安装步骤,如下内容:

79

80

81

82

83

84

RUN git clone https://github.com/pytorch/vision torchvision && \

    cd torchvision && \

    git checkout ${TORCHVISION_VERSION} && \

    python3 setup.py install && \

    cd ../ && \

    rm -rf torchvision

Dockerfile.tensorflow文件里有执行protobufprotoc的编译安装步骤,如下内容:

76

77

 

78

 

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

RUN cd /tmp && \

    wget --quiet --show-progress --progress=bar:force:noscroll --no-check-certificate ${PROTOBUF_URL}/$PROTOBUF_DIR.zip && \

    wget --quiet --show-progress --progress=bar:force:noscroll --no-check-certificate ${PROTOBUF_URL}/$PROTOC_DIR.zip && \

    unzip ${PROTOBUF_DIR}.zip -d ${PROTOBUF_DIR} && \

    unzip ${PROTOC_DIR}.zip -d ${PROTOC_DIR} && \

    cp ${PROTOC_DIR}/bin/protoc /usr/local/bin/protoc && \

    cd ${PROTOBUF_DIR}/protobuf-${PROTOBUF_VERSION} && \

    ./autogen.sh && \

    ./configure --prefix=/usr/local && \

    make -j$(nproc) && \

    make check -j4 && \

    make install && \

    ldconfig && \

    cd python && \

    python3 setup.py build --cpp_implementation && \

    python3 setup.py test --cpp_implementation && \

    python3 setup.py bdist_wheel --cpp_implementation && \

    cp dist/*.whl /opt && \

    pip3 install dist/*.whl && \

    cd ../../../ && \

    rm ${PROTOBUF_DIR}.zip && \

    rm ${PROTOC_DIR}.zip && \

    rm -rf ${PROTOBUF_DIR} && \

    rm -rf ${PROTOC_DIR}

Dockerfile.ml里面执行OpenCV的编译安装步骤,如下内容:

138

139

 

141

142

ARG OPENCV_URL=https://nvidia.box.com/shared/static/5v89u6g5rb62fpz4lh0rz531ajo2t5ef.gz

ARG OPENCV_DEB=OpenCV-4.5.0-aarch64.tar.gz

 

COPY scripts/opencv_install.sh /tmp/opencv_install.sh

RUN cd /tmp && ./opencv_install.sh ${OPENCV_URL} ${OPENCV_DEB}

上面这三个部分是大部分创建深度学习相关应用的Docker镜像所需要的步骤,现在可以直接从Jetson-containers这些配置文件中,复制相关步骤到自己的配置文件中,节省大量的尝试与摸索的时间。

  1. 小结:

为智能边缘设备创建Docker版本镜像,对应用工程师是一项非常重要的技能,因为这个关系到将来的大量部署与长期维护的问题,因此学习使用“docker build”指令配合Dockerfile配置文件的方式,是一项必备的能力。

 

这个Jetson-containers项目作者为了广泛满足各种状况,特别是JetPackL4T版本变化以及对应的TensorFlowPyTorchOpenCV版本,因此使用多个变量进行调节,但这种方法会让配置文件内容变得相当复杂。

本系列文章的目的就是为大家解开这些变量的意义,让读者能清楚识别出这些变量之间的关系,提升对Dockerfile配置文件的了解,最终协助读者进一步简化出自己所需要的特定脚本与配置内容,以自己创建Docker镜像的能力。

来源:业界供稿

0赞

好文章,需要你的鼓励

2022

09/22

11:31

分享

点赞

邮件订阅