docker用gpu的参数_如何构建包含TensorFlow/Python3/Jupyter的Docker?

在前面两个小节中,我们讨论了Docker的基本用法。

由于TensorFlow+Python3+Jupyter这样的开发环境,基本上是很多机器学习(深度学习)爱好者的标配。

所以,在本小节,我们就简单讨论一下如何利用Docker技术,来快速搭建这样的开发环境。

3. 下载合适的Docker镜像

首先,我们要下载合适的Docker镜像。

利用前面所学的命令知识,我们很容易搜索到与TensorFlow相关的Docker镜像:

docker search tensorflow

bc35bda64ab64ae9b2f68324c3ddaf19.png
图3-1 查询与TensorFlow相关的镜像

如果我们之间下拉(pull)星星(starts)排名第一的镜像,它很可能不是我们想要的。这是因为,第一,TensorFlow默认Python 2.7,而不是我们想要的Python 3.x。第二,它没有预装TensorFlow,我们还得手动安装这个软件。

怎样才能解决这个问题呢?

这时就得知道TensorFlow的各种标签(tag)。

根据 TensorFlow官方的信息,其 Docker 映像位于 tensorflow/tensorflow Docker Hub 代码库中。映像版本按照以下格式进行标记:

标记(tag) 说明
latest TensorFlow CPU 二进制映像的最新版本。默认。
nightly TensorFlow 映像的每夜版。(不稳定) version 指定 TensorFlow 二进制映像的版本,例如:1.13.0
devel TensorFlow master 开发环境的每夜版。包含 TensorFlow 源代码。

每个基本标记都有用于添加或更改功能的变体:

标记变体 说明 tag-gpu 支持 GPU 的指定标记版本。 tag-py3 支持 Python 3 的指定标记版本。 tag-jupyter 带有 Jupyter 的指定标记版本(包含 TensorFlow 教程笔记本)

我们可以一次使用多个变体。例如,以下命令会将 TensorFlow 版本映像下载到计算机上:

docker pull tensorflow/tensorflow # latest stable release
docker pull tensorflow/tensorflow:devel-gpu # nightly dev release w/ GPU support
docker pull tensorflow/tensorflow:latest-gpu-jupyter # latest release w/ GPU support and Jupyter

如果我们想下载如标题所示的镜像,就要用到多个tag的叠加(冒号『:』后面就是tag的位置,多个tag用『-』隔开),如下命令所示:

docker pull tensorflow/tensorflow:latest-py3-jupyter

如果我们想下载对应的GPU版本,就把上述命令修改为:

docker pull tensorflow/tensorflow:latest-gpu-py3-jupyter

当然,如果你想下载GPU版本的Docker,首先你的宿主机需要事先安装有合适的GPU,第二,还得安装正确的驱动。可以用如下命令来检查GPU驱动是否安装成功(如图3-2所示):

nvidia-smi

91b1f3b21123a1015131a1992509fedf.png
图3-2 查看GPU

当这个镜像下载完毕之后,我们可以用如下命令查看它(如图3-3所示):

docker image ls

79a428918892a37a3f57beca8462104c.png
图3-3 查看Docker下载的镜像文件

4. 启动Docker

4.1 测试Tensorflow 的执行

首先我们使用如下命令启动Tensorflow(如图3-4所示):

$ docker run -it --rm -p 8888:8888 tensorflow/tensorflow:latest-gpu-py3-jupyter bash

6c9d90ff7723d24a95888f149698fffe.png
图3-4 启动容器

我们来简单解释上面的命令:

  • -it:表示创建交互式终端(interactive terminal),它对应后面的bash(bash是一个为GNU计划编写的Unix shell)
  • --rm:表示在本次容器运行完毕后,自动删除(remove)该容器。需要注意的是, 该参数前是两个短横杠『--』。如果我们想持久化保存对docker 容器的修改,以便下一次使用的话,这个『--rm』选项,就不要添加。
  • -p(小写):指定要映射的IP和端口,但是在一个指定端口上只能绑定一个容器。其格式为hostPort:containerPort(宿主机端口:容器端口)。这里, 8888:8888的含义就是将本地的 8888 端口映射到容器的 8888 端口。

如果我们想启动CPU版本,只需要更改对应的Docker名称即可:

$ docker run -it --rm -p 8888:8888 tensorflow/tensorflow:latest-py3-jupyter bash

在进入Docker的终端之后,我们在输入如下有关Jupyter的配置命令:

root@5c973987de83:/tf# jupyter notebook --ip 0.0.0.0 --allow-root --port 8888 --no-browser

我们也简单解释上面的命令,其中root是用户名,从图3-4可以看出,Docker是不推荐使用root账号登录的。随后的5c973987de83就是这个容器的ID。

jupyter notebook 是在终端启动Jupyter的命令。

--ip 是指定访问Jupyter服务器的IP地址,默认值是127.0.0.1或localhost, 这样无法远程访问的. 这里我们设置为0.0.0.0,表示它可以接纳任何IP。

--allow-root:用户root用户登录

--port 8888:开启8888端口,这个要和前面启动Docker命令的设置一致即可(不一定非得送8888,保持设置一致就行)

--no-browser:表示不需要启动浏览器。后期我们自己手动启动它。

一旦上述命令执行后,便会启动后台Jupyter服务器进程,如图3-5所示。

f1b141176b5181861524d477bfb13c4b.png
图3-5 在Docker内部启动Jupyter服务器

我们要记住最后的那个token(类似访问口令):

http://(5c973987de83 or 127.0.0.1):8888/?token=dd24b802377a125bb217394261af061dc96ba52f8755efa4

然后我们在宿主机的浏览器上输入:

http://127.0.0.1:8888/token=dd24b802377a125bb217394261af061dc96ba52f8755efa4

即可进入如图所示的访问界面。

这证明我们可以正常使用Docker容器内部的Jupyter了!

56f2ecad41e28dfbc3015b329766bd4f.png
图3-6 Docker 中的Jupyter在宿主机浏览器上显示

在图3-5中,我们看到,Jupyter服务器进程占据一个终端界面,我们无法关闭它,因为一旦关闭这个终端,那么这个Jupyter服务器进程就会死亡。其中的逻辑是这样的,我们在终端通过命令行开启了Jupyter服务进程,因此,终端是父进程,Jupyter服务器进程是终端进程的子进程,该子进程因父进程而存在,一旦爹没了,孩子也就失去了依靠。这样就好比『皮之不存毛将焉附』。

5.解决方案

有两种方式可以解决上述问题。

(1)保留现有局面,『另辟蹊径』。

这里的『另辟蹊径』是指,保持图3-5的界面不变,在宿主机上重新打开一个终端,然后在新终端上输入『docker ps -a』命令,查看当前运行的所有容器。然后查询到正在运行的目标容器ID,如c1fd7d9c9b5f(这个值因为『--rm』选项的存在,每次运行后,容器的ID都不一样,无需记忆,只需拷贝),如图3-7所示。

5a05988548a195901a987e918eceeef0.png
图3-7 利用docker ps -a查看运行容器的ID

然后我们利用如下命令重新进入它的交互式终端,如图3-8所示。

docker exec -it c1fd7d9c9b5f bash #进入容器ID为 c1fd7d9c9b5f的终端shell(

e65931b4a00072bef3be21fb19d7eef4.png
图3-8 进入正在运行容器的的终端

这里简单解释一下docker命令的一个重要参数选项『exec』:

exec: Run a command in a running container(在一个正在运行的容器中执行命令)

它和另外『start』选项的不同在于:

docker start命令,直接将已经终止的容器启动运行起来(Start one or more stopped containers)。

这样一来,Docker容器一方面提供了TensorFlow+Jupyter服务,另一方面,又愉快地提供了我们需要的交互式的终端服务。

(2) 后台运行Jupyter,前台照常使用bash

还有一种方法,就是利用前面我们介绍的如何搭建Jupyter服务器的方法,请参考:

玉来愈宏:如何设置远程访问的Jupyter Notebook服务器-04(服务器篇)​zhuanlan.zhihu.com
a8a86a0d53a4e1465198b16e07e128c7.png

在容器内部,使用如下命令:

nohup jupyter notebook --ip 0.0.0.0 --allow-root --port 8888 --no-browser &

其中,nohup的含义,nohup就是不挂起的意思( no hang up)。该命令的一般形式为:

nohup command &

使用&命令后,作业被提交到后台运行,当前终端(控制台)没有被占用。

然后,输入回车键,将Jupyter服务器切换到后台。这时,Jupyter服务器和终端是没有关系的,即使终端关闭了,Jupyter服务还会照常提供(如图3-9所示)。

b0ac6fcd47faf1dd0e1d423bf16df48a.png
图3-9 将Jupyter服务器切换到后台

这里需要注意的是,由于在宿主机的浏览器上,还需要用到Jupyter给出的token,才能使用Jupyter,而Jupyter的输出全部定向输出到nohup.out文件中,它是一个文本文件,因此,我们需要用cat命令输出它,这样就可以查看到这个token。

cat nohup.out

在输出的结果中(如图3-9),拷贝token,在宿主机浏览器地址栏中输入:

http://127.0.0.1:8888/?token=a05597ed1cb93aefec1a9d006741191551a5d9650185f90b

于是,你就能看到类似于图3-6的Jupyter界面。聪慧如你,你肯定观察到了,『127.0.0.1』就是本机(local host)的意思。

那么,问题来了,如何把docker当做一个可以远程访问服务器来使用呢?如何避免使用『繁琐的token』来使用Jupyter呢?

这是我们下一节将要讨论的内容。


本文作者:张玉宏。著有《深度学习之美:AI时代的数据处理与最佳实践》(张玉宏著,电子工业出版社,2018年7月出版,已重印6次,繁体版发行至中国台湾)。更多理论推导及实战环节,请参阅该书。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值