本文大部分内容参考知乎文章
Docker+PyCharm快速搭建机器学习开发环境
搭建过程中出现ssh连接问题可以查看最后的注意事项
Docker是一种容器技术,类似于虚拟机,但比虚拟机更轻便。Docker容器内的应用程序直接运行于宿主的内核,而没有自己的内核,而且也没有硬件虚拟。更多Docker的相关知识可以看《Docker-从入门到实践》。
Deepo是一个包含一系列Docker镜像的项目,这些镜像中包含了TensorFlow、Caffe和Torch等多种深度学习框架。也就是说,在这些镜像中已经包含了大部分流行的机器学习框架,只需要将镜像下载到本地,运行容器即可直接使用这些框架。
Deepo提供了GPU和CPU版本的框架,这里使用的mac以CPU的镜像为例子,对于GPU版本的镜像需要先安装Nvidia官方的nividia-docker和相应版本的NVIDIA驱动。
在github页面可以看到Deepo拥有众多的不同的镜像,以tag来区分,可以根据需要下载对应的镜像。这里以docker pull ufoym/deepo
为例,这样会默认下载包含GPU版本的深度学习框架的镜像。
如果只想要使用CPU的环境的话可以在后面加上CPU,即docker pull ufoym/deepo:cpu
在有了Deepo镜像之后,为了方便使用,可以在Deepo镜像基础上配置ssh服务,以便于mac通过ssh连接登录到容器,以及PyCharm调用远程的python的interpreter。
登录到现有的Deepo容器,以docker run -it ufoym/deepo:cpu bash
交互式的进入deepo容器中。
配置容器ssh连接 这一步可以使用mac通过ssh连接ubuntu容器。首先通过apt-get install openssh-server
用于开启ssh服务的外部连接。
如果出现以下错误:
E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
可以查看这篇文章解决:
Could not get lock /var/lib/dpkg/lock - open 解决方法
配置sshd 修改sshd的默认配置,编辑文件/etc/ssh/sshd_config
,修改文件中的以下三行:
PermitRootLogin yes # 可以登录 root 用户
PubkeyAuthentication yes # 可以使用 ssh 公钥许可
AuthorizedKeysFile .ssh/authorized_keys # 公钥信息保存到该文件中
我的配置文件AuthorizedKeysFile .ssh/authorized_keys
这一行有点不同,是这样的
AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
重启sshd /etc/init.d/ssh restart
使得这些配置生效。
添加你的机器的公钥到容器 这一步是为了能免密码ssh登录到容器中。
mkdir ~/.ssh
touch ~/.ssh/authorized_keys
ssh-keygen -t rsa -C "[email protected]"
(替换为你自己的邮箱),会在~/.ssh
目录下生成三个文件id_rsa
、id_rsa.pub
、known_hosts
。复制id_rsa.pub
文件中的内容。~/.ssh/authorized_keys
文件中。提交修改到镜像 以上对容器的修改并不会改变镜像文件,需要提交修改生成一个新的镜像。
docker ps -a
查看刚刚使用deepo容器,记录下该容器的CONTAINER ID
,例如8b5a86d18e58
。docker commit -m 'add ssh' -a 'your-name' 8b5a86d18e58 deepo-ssh
这样会将刚刚在deepo容器中配置的ssh服务保存,并生成新的deepo-ssh镜像。在后续使用docker images
命令可以查看到新的镜像已经被保存。运行最终的容器
docker run -it -p 12622:22 -v ~/data:/data -v ~/config:/config deepo-ssh:1.0 /bin/bash && /usr/sbin/sshd -D
如果想要运行GPU环境的话,那么必须在启动容器时加上--runtime=nvidia
,那么此时的命令为:
docker run --runtime=nvidia -it -p 12622:22 -v ~/data:/data -v ~/config:/config deepo-ssh:1.0 /bin/bash && /usr/sbin/sshd -D
这样就可以通过ssh -p 12622 root@localhost
连接到容器,可以进入python解释程序,执行import torch
等命令查看机器学习框架是否能正常使用。在exit
退出ssh连接后,容器仍运行在后台。
首先明确的是容器中的22端口已经绑定到主机上的12622端口,那么此时如果想要远程连接的话那么应该采用如下命令:
ssh -p 12622 root@<你的主机的ip地址>
这里有个坑注意。如果你的服务器主机是内网的,要想正确访问的话,那么必须首先搭建隧道。可以参考我之前的博客文章,反向代理搭建隧道
我用autossh搭建隧道不起作用,无法远程登录进行容器里面,但是使用ssh搭建的就可以正确访问
其中ssh的命令为:ssh -fCNR 2064:localhost:12622 <公网机器上用来做转发的账户>@<你的公网机器的ip地址>
具体的参数含义可以参考上面给出的文章链接。
这样就将公网机器上的2064
端口给绑定到你的内网机器的12622端口上了(假定你的服务器是在内网的,这样通过反向代理就可以通过外网进行访问了),即通过ssh就可以进行远程登录容器了:
ssh -p 2064 root@<你的公网主机的ip地址>
首先编写Dockerfile,由于之前已经提交过一次镜像,我们可以基于之前的镜像进行重新的构建一个新的镜像,这样设置里面的root的账户密码为自定义密码。在一个空目录下,创建Dockerfile文件,然后添加如下内容:
FROM deepo-ssh:1.0
RUN echo "root:123456" | chpasswd
然后再次构建镜像,在Dockerfile文件所在的目录执行如下命令:
docker build -t deepo-ssh:2.0 .
这样就创建了deepo-ssh:2.0的镜像,然后基于这个镜像启动容器root账户默认的密码既是你自己设置的了。
启动容器
docker run -it -p 12622:22 -v ~/data:/data -v ~/config:/config deepo-ssh:2.0 /bin/bash && /usr/sbin/sshd -D
注意这里是deepo-ssh:2.0
如果ssh连接不上容器 ,那么在容器中 重启一下ssh服务
/etc/init.d/ssh restart
经过以上的操作,可以理解成本地12622端口开启了ssh服务,运行一个独立的ubuntu服务器。接下来介绍如何使用PyCharm调用Docker容器中的解释器。(注意需要PyCharm专业版)
在Pycharm中file–>settings–>Project Interpreter,如下图所示:
然后点击Add进行添加python解释器
然后选择你已经配置好的ssh连接,进行配置python解释器:
接下里选择解释器,这里一定注意interpreter的地方,要选择正确;然后配置同步目录(即你的本地项目会同步到容器中的哪个目录)
点击finish就配置完成了,接下来就可以进行本地开发,远程运行在容器里了。
注意这里的同步目录最好是之前设置的启动容器时挂载的目录,即最好在/data下
,这样容器销毁了数据也不会丢失
在服务器上创建docker容器并运行在后台,映射到服务器的一个端口。在Pycharm中调用远程服务器的解释器,并创建本地目录和服务器目录的映射(在Deployment配置),就可以实现在本地写代码和调试。
如果发现ssh连接不上,那么可以在容器内进行重启下ssh服务
/etc/init.d/ssh restart