For whom
点开这篇文章的童鞋大多数是刚听过docker这个词或者是早就听过这个词但是却没有仔细了解过,但是发现网上的教程又太过理论,初学者难以快速入门或者不知道从何学起,那么恭喜你,这篇文章就是为你而写。
Outline
Docker是什么?先来一段百度百科上的定义:
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
上面的一段话总结起来主要有三点:1.docker的作用是可以将项目及其所需环境一起打包起来,完整移植到另外一个机器上。2.docker是一项虚拟化技术,虚拟化的目的是为了在同一个主机上运行多个系统或应用,提高资源利用率。3.docker的产生的多个环境是完全独立的,不能相互影响。
认识两个概念
Docker里有两个非常重要的概念, images,container,这两个概念都跟打包好的项目环境有关。简单来说,images是镜像,相当于面向对象里面的类,container是容器,相当于面向对象里面的实例,那么我们知道类是可以产生实例的,但在dcoker里不同的是 容器也可以生成镜像.
总体步骤:主机A build镜像---push到docker hub---主机B pull镜像
实战
话不多说,下面就举个实际例子,来帮助大家快速入门docker python项目部署。
假如我的朋友小Xi(又无中生友了..)是一个深度学习炼丹师,最近在忙活一个人脸检测项目,经过多次优化,终于得到了一个精度和速度都非常棒的模型,现在他的Leader要让他给甲方当面展示下模型,甲方提出了一个要求:模型必须在甲方提供的主机上运行,以防乙方得到的模型数据是在硬件配置非常高的环境下得到的。小Xi理解甲方的顾虑,但是这万一甲方的电脑环境配置有问题,到时候现场演示代码报错怎么弄啊,这时候小Xi的同事小Liu站出来说,你可以试试docker啊,小Xi一拍脑袋,对啊,docker的作用不正是将项目和依赖环境一起打包吗,说干就干,甩了(暴露了《鬼吹灯》铁粉的身份)!
本地的项目文件如下图所示,我们要给甲方运行的主文件是evaluate_image.py, 那么我们接下来的任务是把这个项目用docker打包起来,并上传到docker_hub,在另一台主机上把这个项目pull下来。
安装
参考docker菜鸟教程准备工作
当你敲了几个docker指令你就会发现,docker怎么这么烦啊,每次都要root权限,那么怎么解决这个问题呢?
groups #查看现在用户所在组的组成员,这时候应该是没有docker的
sudo groupadd docker # 添加docker用户组
sudo gpasswd -a xi docker #"xi"是自己的用户名,将你的用户名加到docker用户组里
newgrp docker #更新用户组
groups #这时再查看用户所在组的组成员,发现这时候有docker了,但是很可能你再开一个shell groups还是没有docker,我弄了好久,电脑重启以后就有了.
这时应该就解决了权限问题。
-
build镜像
首先按照这样的方式建立目录,其中docker_file里面是所有的项目代码,Dockerfile是我们自己建立的文件用于生成镜像
.
├── docker_file
└── Dockerfile
现在你的目录应该是这个样子
下面来填写Dockerfile的内容:
FROM python:2.7 #你的项目的工作环境
ADD ./docker_file /file #./docker_file是本地的项目的相对路径, /file是你要建立的镜像里面的项目的相对路径
WORKDIR /file #镜像的工作路径
##下面三行用于添加阿里源,官方源pip安装速度太慢
RUN pip install -U pip
RUN pip config set global.index-url http://mirrors.aliyun.com/pypi/simple
RUN pip config set install.trusted-host mirrors.aliyun.com:
RUN pip install -r requirements.txt #用pip为镜像安装项目的依赖库
CMD ["python", "/file/evaluate_image.py"] #指定项目主文件
需要着重关注的是requirements.txt的生成方法,这个文件里面包含了项目所有的依赖库,当然你可以一行一行的打进去,幸运的是,Python里面提供了一个包可以自动生成项目的依赖库pipreqs,首先你需要安装这个库:
pip install pipreqs
然后cd到项目目录:
pipreqs ./
这时,你会发现docker_file文件夹下面出现了一个requirements.txt,打开里面的内容如下:
tensorflow==1.4.1
easydict==1.9
numpy==1.13.3
切回到docker项目根目录,使用下面的指令,新建镜像
用下面的指令查看目前存在的所有镜像,我们看到了刚才建立的xi_test镜像,你会发现,怎么每个镜像文件都这么大啊,会不会把我的硬盘空间吃完,别担心,docker采用的技术可以和已有镜像共享相同的部分,因此实际并没有占据那么多空间。
docker images
- push镜像到docker hub
既然本地已经有新建的镜像了,那么我们就把它上传到docker hub,先去docker hub注册一个账号,比如我的账号是xyl123,然后建立一个仓库,如first,那么这个仓库就可以用xyl123/first来指代.
docker login #登录docker
docker tag xi_test xyl123/first #必须给本地镜像打上这样的tag标签,才可以传到docker hub上
docker push xyl123/first
这时打开自己的docker hub主页会发现已经存在了刚上传的image
- pull镜像到本地
经过上面的步骤小Xi已经把自己的镜像传到docker hub上面了,只需要甲方安装docker环境,并且在演示的时候用甲方的主机把docker hub上的镜像pull下来就好了。
docker pull xyl123/first #通过运行docker images 你会发现本地多出了一个镜像,接下来你就可以利用images的相关指令对pull下来的images进行操作了.
- 运行镜像
运行镜像的结果是产生一个container,这个container就是我们的项目及其环境。
docker run -it xyl123/first /bin/bash #运行镜像,产生一个容器,并以shell的交互形式运行容器.
可以看到我们产生了一个容器,并且进入了该容器,而且进入的文件夹正是我们在Dockerfile里面设置的工作目录/file,一旦进入了容器,你就可以像操作本地文件的方式操作容器里的文件。
root@50666281fef3:/file# 中的50666281fef3是该容器的id,如果你想查一下本地还有哪些容器,可以新建一个终端使用(不要在容器内使用):
docker ps #查看正在运行的container,
docker ps -a # -a可以查看所有的container
那如果你想删除、开启,停止,进入,退出一个容器呢?
docker rm container_id #运行某个container
docker stop container_id #停止某个container
docker start container_id #运行某个container
docker stop container_id #停止某个container
docker exec -it container_id /bin/bash #进入某个container
exit #退出container,退出后容器并不停止,这是和 docker attach container_id 方式进入容器的根本的不同
- 容器生成镜像
如果在跟甲方演示的时候,甲方提了一些建议,小 Xi修改了生成的容器的内容,为了将修改之后的环境上传到docker hub,供后续改进,这时候需要用改好的容器生成一个镜像。
docker commit 50666281fef3 modified_test_xi
这时候再运行docker images,就可以发现新生成的images了。
-
容器和本地文件互传
假如说,甲方要保存刚才容器内运行的结果到本地,用docker -ps 指令找到刚才容器对应的name
docker cp epic_elbakyan:/file/image/result/宋茜_2.jpeg ./
这时本地就出现了容器内跑出的结果,这不是宋茜的人脸(大)人头(长腿)吗?真的很方便。如果想反过来的,只需要颠倒本地和容器地址的位置。
docker cp epic_elbakyan: ./ 宋茜_2.jpeg /file/image/result/
注意上面两个指令不是在容器内部运行的,是在本地运行的。
日常鸡汤
工欲善其事必先利其器,对一个算法工程师而言,每天仅仅沉醉于阅读paper不可自拔,是远远不够的,要睁开眼睛看看世界,合理利用日新月异的技术帮助自己提高效率,同样的,对于一个负责落地的开发工程师来说,也应该了解必要的理论知识,提升代码的准确性。因此想要成为一个领域内极其优秀的人才,理论和工程能力如人之双腿,缺一不可。