使用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环境请参考这里


最后,祝您身体健康,再见!

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