使用dockerfile構建docker鏡像--以配置SNIPER算法運行環境爲例

最近使用linux環境,發現這個系統給的root權限太高了,常常配環境和依賴庫的時候不小心把別的變量改了,或者是裝錯了依賴庫版本,導致系統無法運行;或者一個算法和另一個算法之間的依賴庫版本不兼容,導致要換依賴庫的版本非常痛苦。

但在linux中,有一個非常好用的技術–docker,它和虛擬機不同,運行代價小,而且可以達到虛擬機快速切換系統環境的功能,可以說是小而精。使用docker部署環境與依賴庫,已經成爲了一種新的技術風向。在tensorflow contribution guideline中,官方指定nvidia-docker爲編譯和修改代碼時的環境配置工具(nvidia-docker 在windows中不可用,詳見這裏)。


Docker簡介

以下內容的docker部分參考自Docker — 從入門到實踐。如果您之前沒有接觸過docker,強烈建議結合其中的基本概念、安裝docker、使用鏡像、操作容器、訪問倉庫的相關章節,來理解下面的內容。

nvdia-docker

如果您需要使用cuda和cudnn相關的庫,則應使用nvdia-docker。請在安裝docker以後,按照Qucikstart中的步驟安裝nvdia-docker插件。

虛擬機和Docker

虛擬機技術(virtual machine)是模擬一個完整的計算機系統。它將一整個系統建立在虛擬化的硬件(infrastructure)之上,而虛擬機軟件(hypervisor),是架起了連接虛擬系統和顯示硬件的橋樑。
在這裏插入圖片描述
由於需要模擬一整套虛擬系統與虛擬硬件,虛擬機技術會佔用大量的硬件資源。這時人們創造了另一種虛擬形式–docker容器。

docker容器(container)是建立在宿主機硬件和系統上的技術,所以不同容器間的系統資源和核心庫是共享的,這意味着,你使用下列兩行代碼得到的結果,竟然是一樣的:

sudo docker run --rm ubuntu:14.04 uname -r
sudo docker run --rm ubuntu:18.04 uname -r

結果是:

4.15.0-46-generic
4.15.0-46-generic

這兩段的代碼做的事情差不多,分別在ubuntu14.04和ubuntu18.04中運行uname命令查看linux核心版本號,你得到的版本號應該是你宿主機系統(Host OS)的版本。而以下兩段代碼,得到的結果是不一樣的

sudo docker run --rm ubuntu:14.04 cat /etc/issue
sudo docker run --rm ubuntu:18.04 cat /etc/issue

結果分別是

Ubuntu 14.04.5 LTS \n \l
Ubuntu 18.04.1 LTS \n \l

因爲/etc/issue文件不屬於系統文件,而是容器中的文件。
在這裏插入圖片描述

虛擬機 docker容器
優點 可以調用所有虛擬系統資源與核心庫 極少運行資源
類似git的分層部署方式,避免冗餘
缺點 運行資源佔用大 非linux系統支持

Docker在windows/mac中

docker在windows和mac中,首先會運行一個docker desktop客戶端,這個客戶端相當於一個小型的linux虛擬機,然後在該虛擬機中啓動docker客戶端程序,所以docker在這兩個系統中的支持和運行速度都比在Linux中(實現方式爲啓動守護程序)要慢一個些。
所以如果您想要體驗原生的docker,推薦使用linux系統。

Dockerfile的編寫方式

在《Docker — 從入門到實踐》中,推薦使用dockerfile的方式構建鏡像,筆者也強烈推薦這個方式。之前我曾使用docker commit方式構建的鏡像,大小約爲dockerfile構建的5倍左右,冗餘非常嚴重,而且由於docker鏡像的層層構建方式,每次commit會導致鏡像越來越大,除非確保做好每次的清理工作。
本次我們使用dockerfile來構建鏡像,會用到兩個命令:RUN和ENV

  • RUN:docker中的RUN、CMD、ENTRYPOINT都可以幹類似的事情,即運行shell命令。具體區別可以參考這。一般來說,我們會使用RUN命令構建多層鏡像。
  • ENV:它可以設定新鏡像中的系統環境變量,以免運行時找不到依賴庫。
    以下是構建SNIPER運行環境的dockerfile:
# 下面這段進行編譯環境佈置
FROM nvidia/cuda:9.2-cudnn7-devel-ubuntu16.04 as env

USER root

RUN apt-get update \
  && apt-get -y install wget locales git bzip2 curl \
  && rm -rf /var/lib/apt/lists/*

RUN localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8

RUN echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \
  && locale-gen en_US.utf8 \
  && /usr/sbin/update-locale LANG=en_US.UTF-8

ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8%

ENV LD_LIBRARY_PATH /usr/local/cuda/lib64

RUN apt-get update \
		&& apt-get -y install \
    libatlas-base-dev \
    libopencv-dev \
    libopenblas-dev \
  && rm -rf /var/lib/apt/lists/*
  
# 下面這段進行運行庫佈置
FROM sniper/env as prod

RUN apt-get update \
		&& apt-get -y install python-pip
 
RUN pip install opencv-python==3.2.0.8 \
    Cython \
    matplotlib==2.2.4 \
    numpy \
    scipy \
    pyyaml \
    EasyDict \
    protobuf \
    argparse \
    scikit-image \
    tqdm \
    futures\
    && rm -rf /var/lib/apt/lists/* \
    && rm -rf ~/.cache/pip/*

ENV LD_LIBRARY_PATH /usr/lib/x86_64-linux-gnu:/usr/local/cuda/lib64
ENV PYTHONPATH /root/SNIPER/SNIPER-mxnet/python:/root/SNIPER/lib

文件已上傳github,地址在此

構建鏡像

下載dockerfile到本地
使用以下命令構建鏡像:

sudo nvidia-docker build -t sniper .

由於dockerfile是分步寫的,所以您也可以使用以下命令構建:

sudo nvidia-docker build --target env -t sniper/env .
sudo nvidia-docker build --target prod -t sniper/prod .

構建完的鏡像大小爲4.01GB。
在這裏插入圖片描述
第二種方式中,你在env編好之後就可以開始SNIPER-mxnet的編譯工作,prod只是增加以下SNIPER的運行庫。無論您使用哪種方式, 不要忘記複製代碼最後的"."


SNIPER簡介

SNIPER是一種目標檢測算法,在coco2017和voc 2007數據集上,都實現了state-of-the-art的檢出精度。這裏是論文代碼
您可以按照這裏的第一步clone代碼
在按照流程構建鏡像之後,您可以使用以下代碼開啓一個容器(默認進入bash)

sudo nvidia-docker run -it -rm -v /root/SNIPER:/home/xxx/python/SNIPER/ sniper/prod

把這裏的/home/xxx替換爲您自己的SNIPER路徑,然後開始編譯SNIPER-mxnet代碼

cd /root/SNIPER/SNIPER-mxnet/
make USE_CUDA_PATH=/usr/local/cuda
cd ..
bash scripts/compile.sh

使用make編譯完成後,您會得到libmxnet.so:
libmxnet
運行scripts/compile.sh後,在nms/bbox/chips中,能看到下面的.so文件
在這裏插入圖片描述

運行SNIPER/demo.py

編譯好之後,先運行scipt/download_sniper_detector.sh下載預訓練模型,再運行demo.py,發現以下輸出結果,大功告成!
在這裏插入圖片描述
關於如何在pycharm中無縫使用nvidia-docker環境請參考這裏


最後,祝您身體健康,再見!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章