本文首发于微信公众号:视觉三维重建 。内容坚持原创,和您分享视觉三维重建领域的经典知识与前沿论文解读,欢迎关注!
1. Docker基础知识
物理服务器部署应用示意图
那么,这种方式有什么问题呢?其实,在物理机上部署应用有以下几个缺点:
虚拟机上部署应用示意图
虚拟机的优点:
虚拟机的不足之处
虚拟机的不足之外来自于对物理服务器资源的消耗,当我们在物理服务器创建一台虚拟机时,便需要虚拟出一套硬件并在上面运行完整的操作系统,每台虚拟机都占用许多的服务器资源。
docker是轻量级的虚拟机
Docker容器与系统关系示意图
Docker是在操作系统进程层面的隔离,而虚拟机是在物理资源层面的隔离,两者完全不同,另外,我们也可以通过下面的一个比较,了解两者的根本性差异。
容器解决了开发与生产环境的问题
开发环境与生产环境折射的是开发人员与运维人员之间的矛盾,也许我们常常会听到开发人员对运维人员说的这样一句话:“在我的电脑运行没问题,怎么到了你那里就出问题了,肯定是你的问题”,而运维人员是认为是开发人员的问题。
开发人员需要在本机安装各种各样的测试环境,因此开发的项目需要软件越多,依赖越多,安装的环境也就越复杂。
同样的,运维人员需要为开发人员开发的项目提供生产环境,而运维人员除了应对软件之间的依赖,还需要考虑安装软件与硬件之间的兼容性问题。
就是这样,所以我们经常看到开发与运维相互甩锅,怎么解决这个问题呢?
容器就是一个不错的解决方案,容器能成为开发与运维之间沟通的语言,因为容器就像一个集装箱一样,提供了软件运行的最小化环境,将应用与其需要的环境一起打包成为镜像,便可以在开发与运维之间沟通与传输。
Docker分为社区版(CE)和企业版(EE)两个版本,社区版本可以免费使用,而企业版则需要付费使用,对于我们个人开发者或小企业来说,一般是使用社区版的。
Docker CE有三个更新频道,分别为stable、test、nightly,stable是稳定版本,test是测试后的预发布版本,而nightly则是开发中准备在下一个版本正式发布的版本,我们可以根据自己的需求下载安装。
本节引用这里
Docker镜像是一个特殊root的文件系统,提供容器运行时所需的程序、库、资源、配置等文件,另外还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。image是用来创建container的,一个镜像可以包含一个完整的操作系统环境和用户需要的其它应用程序;一个镜像可以创建多个容器。
操作镜像的命令
Docker中与镜像操作相关的命令都在docker image这条子命令下,通过docker image --help这条命令,可以看到docker image子命令的详细文档,如下:
Usage: docker image COMMAND
Manage images
Commands:
build Build an image from a Dockerfile(构建镜像的命令)
history Show the history of an image(显示镜像构建历史过程)
import Import the contents from a tarball to create a filesystem image(导入一个由容器导出的镜像)
inspect Display detailed information on one or more images(显示一个镜像的详细信息)
load Load an image from a tar archive or STDIN(从一个文件或标准输入流中导入镜像)
ls List images(查看镜像列表)
prune Remove unused images(删除虚悬镜像)
pull Pull an image or a repository from a registry(从仓库拉取镜像)
push Push an image or a repository to a registry(推送镜像到仓库)
rm Remove one or more images(删除镜像)
save Save one or more images to a tar archive(streamed to STDOUT by default)(保存镜像到文件)
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE(给镜像打标签)
容器是镜像创建的==实例==。它可以被启动、开始、停止、删除。每个容器都是 相互隔离的、保证安全的平台。
操作容器的相关命令
Usage: docker container COMMAND
Manage containers
Commands:
attach Attach local standard input, output, and error streams to a running container
commit Create a new image from a container's changes(把容器保存为镜像)
cp Copy files/folders between a container and the local filesystem
create Create a new container(创建一个新的容器)
diff Inspect changes to files or directories on a container's filesystem
exec Run a command in a running container(在一个运行的容器中执行命令)
export Export a container's filesystem as a tar archive
inspect Display detailed information on one or more containers
kill Kill one or more running containers(杀死一个或多个正在运行的容器)
logs Fetch the logs of a container
ls List containers(显示本地容器列表)
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
prune Remove all stopped containers
rename Rename a container(重命名容器)
restart Restart one or more containers(重启一个或多个容器)
rm Remove one or more containers(删除一个或多个容器)
run Run a command in a new container(运行一个新的容器)
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers(停止一个或多个容器)
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
wait Block until one or more containers stop, then print their exit codes
仓库是集中存放镜像文件的场所;每个 仓库中又包含了多个镜像,每个镜像有不同的标签(tag);最大的公开仓库是DockerHub,存放了数量庞大的镜像供用户下载。国内的公开 仓库包括DockerPool等,可以提供大陆用户更稳定快速的访问。当然,用户也可以在本地网络内创建一个私有仓库。 问题一:Image与Container之间的联系? 答:镜像的概念更多偏向于一个环境包,这个环境包可以移动到任意的Docker平台中去运行;而容器就是你运行环境包的实例。你可以针对这个环境包运行N个实例。换句话说container是images的一种具体表现形式。你也可以认为镜像与你装载操作系统iso镜像是一个概念,容器则可理解为镜像启动的操作系统。一个镜像可以启动任意多个容器,即可以装载多个操作系统。
强烈推荐阅读
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
& apt-get update
(如果已经安装了旧版本:先 sudo apt-get remove docker docker-engine docker.io containerd runc
)sudo groupadd docker && sudo gpasswd -a ${USER} docker && sudo service docker restart
然后重启terminaldocker pull nvidia/cuda:10.1-cudnn7-devel
docker images
docker run -it --gpus all IMAGEID
后,相当于进入了Ubuntu环境,只是没有界面,然后正常安装配置各种生产环境。docker commit -a "author" -m "describe" curr_ContainerID new_ContainerID:TAG
打包当前运行的容器成为新的容器docker save -o xx/yy.tar ContainerID:TAG
保存当前image到本地docker export -o xx/yy.tar ContainerID:TAG
不保存历史操作记录的方式保存image到本地,相当于减少占用空间。import cv2 libGL.so.1: cannot open shared object file: No such file or directory
soultion: sudo apt update sudo apt install libgl1-mesa-glx
ln -s /usr/bin/python3 /usr/bin/python
/usr/local/bin
是当前用户的路径 ,/usr/bin
是超级管理员路径前面的方式配置docker生产环境非常麻烦,新增环境时,又要重新打包image,且image大小会越来越大,所以一般都通过编写dockerfile的方式来配置环境。dockerfile的写法较为讲究,写的严谨可以大幅减小image的大小。后期添加包环境时,只需要添加命令层即可。以下是可以参考的示例:
1. opencv
FROM nvidia/cuda:10.1-cudnn7-devel
LABEL maintainer="yxiang"
ARG OPENCV_VERSION="3.4.5"
# install dependencies
RUN apt-get update
RUN apt-get install -y libopencv-dev yasm libjpeg-dev libjasper-dev libavcodec-dev libavformat-dev libswscale-dev libdc1394-22-dev libv4l-dev python-dev python-numpy libtbb-dev libqt4-dev libgtk2.0-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev x264 v4l-utils pkg-config
RUN apt-get install -y curl build-essential checkinstall cmake
# download opencv
RUN curl -sL https://github.com/Itseez/opencv/archive/$OPENCV_VERSION.tar.gz | tar xvz -C /tmp
RUN mkdir -p /tmp/opencv-$OPENCV_VERSION/build
WORKDIR /tmp/opencv-$OPENCV_VERSION/build
# install
RUN cmake -DWITH_FFMPEG=OFF -DWITH_OPENEXR=OFF -DBUILD_TIFF=OFF -DWITH_CUDA=OFF -DWITH_NVCUVID=OFF -DBUILD_PNG=OFF ..
RUN make
RUN make install
# configure
RUN echo "/usr/local/lib" > /etc/ld.so.conf.d/opencv.conf
RUN ldconfig
RUN ln /dev/null /dev/raw1394 # hide warning - http://stackoverflow.com/questions/12689304/ctypes-error-libdc1394-error-failed-to-initialize-libdc1394
# cleanup package manager
RUN apt-get remove --purge -y curl build-essential checkinstall cmake
RUN apt-get autoclean && apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# prepare dir
RUN mkdir /source
VOLUME ["/source"]
WORKDIR /source
CMD ["bash"]
2. detectorn2
FROM nvidia/cuda:10.1-cudnn7-devel
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y
python3-opencv ca-certificates python3-dev git wget sudo
cmake ninja-build &&
rm -rf /var/lib/apt/lists/*
RUN ln -sv /usr/bin/python3 /usr/bin/python
# create a non-root user
ARG USER_ID=1000
RUN useradd -m --no-log-init --system --uid ${USER_ID} appuser -g sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER appuser
WORKDIR /home/appuser
ENV PATH="/home/appuser/.local/bin:${PATH}"
RUN wget https://bootstrap.pypa.io/get-pip.py &&
python3 get-pip.py --user &&
rm get-pip.py
# install dependencies
# See https://pytorch.org/ for other options if you use a different version of CUDA
RUN pip install --user tensorboard
RUN pip install --user torch==1.6 torchvision==0.7 -f https://download.pytorch.org/whl/cu101/torch_stable.html
RUN pip install --user 'git+https://github.com/facebookresearch/fvcore'
# install detectron2
RUN git clone https://github.com/facebookresearch/detectron2 detectron2_repo
# set FORCE_CUDA because during `docker build` cuda is not accessible
ENV FORCE_CUDA="1"
# This will by default build detectron2 for all common cuda architectures and take a lot more time,
# because inside `docker build`, there is no way to tell which architecture will be used.
ARG TORCH_CUDA_ARCH_LIST="Kepler;Kepler+Tesla;Maxwell;Maxwell+Tegra;Pascal;Volta;Turing"
ENV TORCH_CUDA_ARCH_LIST="${TORCH_CUDA_ARCH_LIST}"
RUN pip install --user -e detectron2_repo
# Set a fixed model cache directory.
ENV FVCORE_CACHE="/tmp"
WORKDIR /home/appuser/detectron2_repo
# run detectron2 under user "appuser":
# wget http://images.cocodataset.org/val2017/000000439715.jpg -O input.jpg
# python3 demo/demo.py
#--config-file configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml
#--input input.jpg --output outputs/
#--opts MODEL.WEIGHTS detectron2://COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x/137849600/model_final_f10217.pkl
dockerfile最佳实践
docker pull henry2423/ros-vnc-ubuntu
参考这里
主要涉及前面的docker环境配置,外加配置SSH连接、端口映射等,文件映射,这样就可以将实验室一台性能强悍的主机配置为炼丹炉,给实验室每个人运行一个docker容器,供大家交替使用GPU资源了,具体配置可参考 : pycharm远程使用服务器端docker
运行命令:docker run -p 5592:5592 -p 5593:5593 -p 8022:22 --name="liuzhen_tf" -v ~/workspace/liuzhen/remote_workspace:/workspace/liuzhen/remote_workspace -it tensorflow/tensorflow:latest-gpu /bin/bash
如果文章对你有帮助,还请您点赞、转发,并关注公众号:视觉三维重建。鼓励作者创作更多优质内容!欢迎关注公众号:视觉三维重建。