前记
最近在学习深度学习,奈何本地没有GPU,于是租用了一台GPU服务器。为了方便调试且管理环境,我想能够本地VSCode连接到服务器的容器中,以此直接在容器中编码。
一、容器准备
服务器起容器
在服务器上启动镜像为:"pytorch/pytorch:1.6.0-cuda10.1-cudnn7-devel" 容器,将服务器的 6776端口(可设置为任意不冲突端口)映射到容器的 22 端口(ssh服务的默认端口),容器起名为 test(可随意配置),启动后默认进入容器中。
docker run -it -p 6776:22 --name test pytorch/pytorch:1.6.0-cuda10.1-cudnn7-devel /bin/bash
注:
- -it:启动后进入容器的交互式界面
- -p:设置本机与容器端口映射,顺序为 hostPort: containerPort
- --name:容器起名字
容器内部准备
成功运行上述命令后,应该进入了容器的交互界面。
更换apt阿里源:
cp /etc/apt/source.list /etc/apt/source.list.bak
sed -i "s/archive.ubuntu.com/mirrors.aliyun.com/g" /etc/apt/source.list
apt-get update
安装 ssh 服务端:
apt-get install openssh-server
开启 ssh 服务端:
service ssh start
配置主机免密登陆(注意是自己的电脑,不是服务器,这里以 mac 为例):
找到主机 ssh 公钥:
cat ~/.ssh/id_rsa.pub
将输出的内容复制到容器中的 ~/.ssh/authorized_keys 文件中,如果文件或目标文件不存在,则创建:
mkdir -p ~/.ssh
cat << EOF > ~/.ssh/authorized_keys
> ${复制的内容}
> EOF
二、主机连接服务器容器
连接服务容器的方案有两种:
方案一
在本地机器输入:
ssh -p 6776 root@${server_ip}
-p 会改变ssh访问的端口,这里改成6776,因此会访问服务器的6776端口,而服务器的6776端口又映射到容器的22端口,所以相当于访问了容器的ssh server所监听的端口,理论上能够达成目标。
但实际上没这么做,因为这需要服务器的外网 ip 开启6776端口,允许 6776 端口的流量进入,而我没有这个权限,因此放弃这个方案。
方案二
在本机输入:
ssh -NL 6776:localhost:6776 root@${server_ip}
-L的解释是:
-L port:host:hostport
将本地机(客户机)的某个端口转发到远端指定机器的指定端口. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 同时远程主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有 root 才能转发特权端口.
简单的理解就是,将本机localhost的6776端口与服务器的6776端口绑定,所有通过 localhost:6776 的数据都会转发到服务器的 6776 端口上。注意这个转发是单向的,即访问 localhost:6776 会转发到 服务器的 6776 端口,但访问服务器的 6776 端口并不会转发到 localhost:6776。如果想实现这个功能,需要另一个参数:-R。附上 ssh 参数解释连接:ssh参数解析。
-N 可以简单理解为什么都不干。如果没有 -N,则输入命令后会直接连接到服务器,占用外网带宽。加上 -N 后,这条命令更像是一条配置规则,规则的有效期就是该命令执行后的阻塞时间(执行完带-N的命令后,会发现终端阻塞了)。
有了上面的步骤,便可以通过执行下面命令来访问容器了。不过只限于上面命令的阻塞期间:
ssh -p 6776 root@localhost
三、VSCode 通过 Remote Explorer 插件连接
在 VSCode 中安装 “Remote Explorer” 插件,并通过 ssh 连接:ssh -p localhost root@localhost
即可。
后记
ssh是一个功能强大命令。