前一篇文章已經對 Jetson-containers 的容器創建腳本進行較為深入的說明,主要是為了更廣泛地適用于不同 JetPack 版本的環境,因此使用嵌套式腳本的處理方式,初看之下會覺得相當繁瑣,不過只要將腳本之間負責傳遞信息的變量內容理清,就會有種豁然開朗的感覺,并不難懂。
本文將帶大家繼續深入了解 Dockerfile 鏡像創建過程中最重要的配置文件內容,更加透徹地了解整個容器鏡像的創建過程。
3、使用 docker_build.sh 腳本創建容器:
在 scripst/docker_build_ml.sh 里有三處調用 scripst/docker_build.sh 腳本的部分,才是真正創建個別容器的環節。
以創建 l4t-pytorch 的 build_pytorch() 函數為例,在第 26 行調用 docker_build.sh 腳本并提供所有需要的相關參數:
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-argOPENCV_DEB=$OPENCV_DEB
再看看 docker_build.sh 內容,里面里其實只有 “docker build -t $CONTAINER -f $DOCKERFILE "$@" .” 這一道創建鏡像的指令,而相關所需要的參數都在上圖中做好完整的配置。
這里調用了主目錄下的 Dockerfile.pytorch,并且以 “--build-arg” 方式將相關參數去對應 Dockerfile.pytorch 配置文件里的變量,這些變量在 Dockerfile 里可能會提供預設值,但是這些新的設定值就會覆蓋掉配置文件的預設值。
創建 l4t-tensorflow 鏡像的方式也是一樣的,在第 172 行 buidl_tensorflow() 函數里第 181~187 行內容(如下),也是調用 docker_build.sh 腳本去執行,不過配置文件改成 Dockerfile.tensorflow,其他需要的參數也有所調整。
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-argOPENCV_DEB=$OPENCV_DEB
在第 275~281 行用同樣的模式去創建 l4t-ml 鏡像,同樣調用 docker_build.sh 腳本,不過配置文件換成 Dockerfile.ml,相關配套參數也要根據配置文件內的實際狀況進行調整,這里就不重復說明。
4、分析 Dockerfile 內容:
這個項目所提供的腳本,主要功能是為將對應的 Dockerfile 進行變量配置的工作,現在以創建 l4t-ml 鏡像會使用到的 Dockerfile.pytorch、Dockerfile.tensorflow 與 Dockerfile.ml 為例,簡單說明一下幾個環節:
1)檢查 Dockerfile 的變量
可以用文字編輯器打開這些文件,使用 “搜索” 功能查找關鍵字 “ARG”,就能輕松找到里面的各項變量與預設值。
下面列出 Dockerfile.pytorch 的 6 個變量與預設值:
ARG BASE_IMAGE=nvcr.io/nvidia/l4t-base:r32.4.4ARG PYTORCH_URL=https://nvidia.box.com/shared/static/xxx.whlARG PYTORCH_WHL=torch-1.2.0-cp36-cp36m-linux_aarch64.whlARG TORCHVISION_VERSION=v0.4.0ARG TORCH_CUDA_ARCH_LIST="5.3;6.2;7.2;8.7"ARGTORCHAUDIO_VERSION
下面列出 Dockerfile.tensorflow 的 9 個變量與預設值:
ARG BASE_IMAGEARG HDF5_DIR="/usr/lib/aarch64-linux-gnu/hdf5/serial/"ARG MAKEFLAGS=-j$(nproc)ARG PROTOBUF_VERSION=3.19.4ARG PROTOBUF_URL=https://。。。/v${PROTOBUF_VERSION}ARG PROTOBUF_DIR=protobuf-python-${PROTOBUF_VERSION}ARG PROTOC_DIR=protoc-${PROTOBUF_VERSION}-linux-aarch_64ARG TENSORFLOW_URL=https://。。。/。。。-linux_aarch64.whlARGTENSORFLOW_WHL=tensorflow-1.15.3+nv20.9-cp36-cp36m-linux_aarch64.whl
下面列出 Dockerfile.ml 的 10 個變量與預設值:
ARG BASE_IMAGE=nvcr.io/nvidia/l4t-base:r32.4.4ARG PYTORCH_IMAGEARG TENSORFLOW_IMAGEARG MAKEFLAGS=-j$(nproc) ARG PYTHON3_VERSION=3.8ARG CUPY_VERSION=v10.2.0ARG CUPY_NVCC_GENERATE_CODE="arch=compute_53。。。"ARG OPENCV_URL=https://nvidia.box.com/shared/static/。。。.gzARGOPENCV_DEB=OpenCV-4.5.0-aarch64.tar.gz
對照一下前面腳本所提供的參數,這樣就能很輕松地了解前面腳本的任務與目的,如果前面腳本中有使用 “--build-arg” 設定的參數值,就會覆蓋配置文件內的預設值。
2)導入所需要的基礎鏡像
這種 docker build 創建容器的方式,是必須基于某個(些)已經存在的基礎容器之上,添加的相關依賴庫與軟件,因此首要工作就是從 “FROM ${BASE_IMAGE}” 導入指定的基礎鏡像開始,在 Dockerfile.pytorch 與 Dockerfile.tensorflow 就是如此,不過在 Dockerfile.ml 文件中還多了以下兩行內容:
FROM ${PYTORCH_IMAGE} as pytorchFROM${TENSORFLOW_IMAGE}astensorflow
就是要從這兩個鏡像里提取 PyTorch 與 Tensorflow 的配套資源,如下所列的指令:
COPY --from=tensorflow /usr/local/bin/protoc /usr/local/binCOPY --from=tensorflow /usr/local/lib/libproto* /usr/local/lib/COPY --from=tensorflow /usr/local/include/google /usr/local/include/googleCOPY --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-pytorch 與 l4t-tensorflow 鏡像,也可以將這兩個框架合并在 l4t-ml 鏡像內,此時只要將前面兩個鏡像已經編譯安裝好的部分復制到新鏡像里面里就可以。
我們當然也可以將 Dockerfile.pytorch 與 Dockerfile.tensorflow 里的安裝步驟全部放入 Dockerfile.ml 里面,不過這樣會讓整個配置文件變得非常冗長,估計要超過 400 行的內容,其最大的麻煩之處是會導致除錯工作變得相當復雜與冗長,因此這里將處理過程進行分割再做合并。
3)安裝依賴庫
在 Dockerfile 配置文件內使用 “RUN” 指定后面要執行的指令,后面加上 Ubuntu 使用的 apt-get install、pip install 等方式安裝依賴庫或軟件。由于鏡像的操作是設定為 root 用戶,因此不需要使用 "sudo" 去取得執行權限。
這個環節的最大困難點是 “要安裝哪些內容”?這就需要整理出軟件原廠所提供的依賴庫列表,這個過程是相對繁瑣的,而 Jetson-containers 項目所提供的 12 個 Dockerfile 參考內容,能讓我們節省很多摸索的時間。
4)需要編譯的部分:
例如在 Dockerfile.pytorch 里面執行 torchvision 的編譯安裝步驟,如下內容:
RUN git clone https://github.com/pytorch/vision torchvision && cd torchvision && git checkout ${TORCHVISION_VERSION} && python3 setup.py install && cd ../ && rm-rftorchvision
在 Dockerfile.tensorflow 文件里有執行 protobuf 與 protoc 的編譯安裝步驟,如下內容:
RUN cd /tmp && wget --quiet --show-progress --progress=barnoscroll --no-check-certificate ${PROTOBUF_URL}/$PROTOBUF_DIR.zip && wget --quiet --show-progress --progress=barnoscroll --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 的編譯安裝步驟,如下內容:
ARG OPENCV_URL=https://nvidia.box.com/shared/static/5v89u6g5rb62fpz4lh0rz531ajo2t5ef.gzARG OPENCV_DEB=OpenCV-4.5.0-aarch64.tar.gz COPY scripts/opencv_install.sh /tmp/opencv_install.shRUNcd/tmp&&./opencv_install.sh${OPENCV_URL}${OPENCV_DEB}
上面這三個部分是大部分創建深度學習相關應用的 Docker 鏡像所需要的步驟,現在可以直接從 Jetson-containers 這些配置文件中,復制相關步驟到自己的配置文件中,節省大量的嘗試與摸索的時間。
5、小結:
為智能邊緣設備創建 Docker 版本鏡像,對應用工程師是一項非常重要的技能,因為這個關系到將來的大量部署與長期維護的問題,因此學習使用 “docker build” 指令配合 Dockerfile 配置文件的方式,是一項必備的能力。
這個 Jetson-containers項目作者為了廣泛滿足各種狀況,特別是 JetPack 的 L4T 版本變化以及對應的 TensorFlow、PyTorch、OpenCV 版本,因此使用多個變量進行調節,但這種方法會讓配置文件內容變得相當復雜。
本系列文章的目的就是為大家解開這些變量的意義,讓讀者能清楚識別出這些變量之間的關系,提升對 Dockerfile 配置文件的了解,最終協助讀者進一步簡化出自己所需要的特定腳本與配置內容,以自己創建 Docker 鏡像的能力。
-
OpenCV
+關注
關注
30文章
628瀏覽量
41259 -
英偉達
+關注
關注
22文章
3743瀏覽量
90830 -
鏡像
+關注
關注
0文章
162瀏覽量
10697 -
Docker
+關注
關注
0文章
454瀏覽量
11814
原文標題:NVIDIA Jetson 系列文章(11):從頭創建Jetson的容器(2)
文章出處:【微信號:NVIDIA-Enterprise,微信公眾號:NVIDIA英偉達企業解決方案】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論