服務器搭建遠程docker深度學習環境
本文大部分內容參考知乎文章
搭建過程中出現ssh連接問題可以查看最后的注意事項
Docker
Docker是一種容器技術,類似於虛擬機,但比虛擬機更輕便。Docker容器內的應用程序直接運行於宿主的內核,而沒有自己的內核,而且也沒有硬件虛擬。更多Docker的相關知識可以看《Docker-從入門到實踐》。
Deepo
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-ssh鏡像
在有了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 "youremail@example.com"
(替換為你自己的郵箱),會在~/.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
- -d | 后台運行
- -p 12622:22 | 綁定當前mac的12622端口到deepo-ssh容器的22端口(ssh服務默認為22端口)
- -v ~/data:/data | 將本機上的~/data目錄掛載到容器/data目錄
- /usr/sbin/sshd -D | 容器運行的命令和參數,開啟ssh服務
這樣就可以通過ssh -p 12622 root@localhost
連接到容器,可以進入python解釋程序,執行import torch
等命令查看機器學習框架是否能正常使用。在exit
退出ssh連接后,容器仍運行在后台。
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地址>
- 第二個坑就是ssh連接時的root的賬戶密碼你是不知道的,因為如果像上面啟動容器后你沒有修改設置密碼,你是不知道root的密碼的,所以你需要在啟動容器后再重新設置一下密碼,這樣ssh連接的時候才能正確登錄。
基於之前的鏡像重新編寫Dockerfile,設置容器啟動時的密碼
-
首先編寫Dockerfile,由於之前已經提交過一次鏡像,我們可以基於之前的鏡像進行重新的構建一個新的鏡像,這樣設置里面的root的賬戶密碼為自定義密碼。在一個空目錄下,創建Dockerfile文件,然后添加如下內容:
FROM deepo-ssh:1.0 RUN echo "root:123456" | chpasswd
- deepo-ssh:1.0 是之前生成的鏡像
- echo “root:123456” | chpasswd 是將root的賬戶密碼默認設置為123456了(這里密碼你可以自行設置)
-
然后再次構建鏡像,在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
PyCharm連接Docker
經過以上的操作,可以理解成本地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