之所以要写这么一篇介绍的文章,主要是因为作为一个打杂的算法工程师,在工作中需要使用远程服务器进行开发,然而远程服务器系统版更新缓慢,总有些代码跑不起来,让调包的我很难办。
另外工作中难免遇到共用开发机器的情况,如果把现在的算法工作称为炼丹,那服务器就是丹房,如果大家共用一个丹炉那总是会有配置不同的问题,因此最好的解决方式就是每个人用自己的丹炉。
基于以上原因,我整理了这么一篇配置,大体方案是基于 Docker + VSCode 配置属于个人的开发环境,还会涉及 VSCode 扩展等。
首先要说明的是,由于个人才疏学浅,本文介绍的方案并不是理论上最优的方案,而且一些配置项也并不是必须或并不是适合所有人的,因此如果有同学想要参考的话建议首先完整阅读下各部分,有了整体的概念之后再根据自身需要参考配置。
其次本文各部分都参考了大量文档文章,我尽量给出了相关的参考链接,在此感谢原作者们。对于给出了具体参考链接的情况本文就不会对具体内容多做描述,还请看官查看相关参考文章。不论是本文还是相关参考资料都存在错误的可能,因此还需要阅读的各位根据自己遇到的情况进行调整,官方文档永远比二手博客文章更靠谱。
最后感谢各位(如果有)看官给本文贡献了点击量和浏览量…
首先要说 Docker 是什么
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化
以上是我抄的百科词条,总体意思看来是做了个内核容器虚拟化,也就是在真实系统的基础上又虚拟化了容器出来。类比的话可以类似于常用的虚拟机,但又不一样,容器开销上会小很多。这种虚拟容器适合用来制作可移植镜像发布应用,而我这里要用它来当做虚拟环境用,不知道算不算是一种浪费。
提到了Docker就要说到它的底层 LXC ,关于 LXC 和 Docker 的关系可以看看 《请问docker与lxc是什么关系,有什么区别》。因为 LXC 是 Docker 的底层,所以也有人用 LXC 来达到共用机器隔离的目的,可以参考《为实验室建立公用GPU服务器》。不过本文还是介绍使用 Docker 的方法,就不多介绍 LXC 了。
知道了Docker 是什么了之后就要使用 Docker,需要说明的是最好参考 docker-docs (注:大家都看过廖雪峰老师的Python等系列博客吧,他在自己的博客里也表示“docker就看官方文档”),一些中文资料如《菜鸟教程-Docker 教程》因为更新不及时可能会存在些问题,这里我是踩过坑的。
以 CentOS7 + 社区版Docker 为例,CentOS7 中 Docker 的安装可以参考《Get Docker Engine - Community for CentOS》
首先 Docker 对系统环境有些要求,参考文档中 《OS requirements 》部分,具体的说就是 CentOS7 以及 centos-extras repository 。
系统符合要求后可以卸载已有老版本 docker,参考 《Uninstall old versions》 部分,没装过的可以跳过了。
接下来的安装部分提供了三种安装方式,分别是常用的由repository安装、使用 RPM package 手动安装以及测试脚本安装,参考文档 《Install Docker Engine - Community》部分,以下简单介绍下常用的安装方式:
第一步 SET UP THE REPOSITORY:
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
第二步就是安装 docker:sudo yum install docker-ce docker-ce-cli containerd.io
,安装后docker并未自动启动
第三步就是启动 docker:sudo systemctl start docker
最后可以测试下docker 是否安装成功:sudo docker run hello-world
,如果能够正确显示一些信息则安装成功
安装完之后如果想卸载了可以参考 《Uninstall old versions》部分卸载 docker,但是卸载时候不会自动删除镜像和容器,需要记得手动删除。
作为一个算法工程师,总归有用上 GPU 的时候,为了在 Linux 上启用 GPU 支持,需要安装 nvidia-docke。
The NVIDIA Container Toolkit allows users to build and run GPU accelerated Docker containers.
要安装 nvidia-docker 首先要确保安装了 NVIDIA driver 和 Docker 19.03,其中驱动的链接已经给出了,没安装的自己安装下。
CentOS7下的 nvidia-docker 的安装可以参考《CentOS 7 (docker-ce), RHEL 7.4/7.5 (docker-ce), Amazon Linux 1/2》,使用说明可以参考《Usage》。
需要注意的是在 Usage 里已经使用 --gpus
参数,而后续的 TensorFlows 的 docker 中文教程中还在使用已废弃 --runtime=nvidia
参数,需要记得替换成--gpus
。
安装好之后可以使用命令 docker run --gpus all,capabilities=utility nvidia/cuda:9.0-base nvidia-smi
测试下。
docker的使用真的是参考 docker-docs 就好了,这里只说几个和后文有关及常用的。
首先是一些查看镜像(image)和容器(container)的命令:
docker image ls
docker image rm [imageName]
docker container ls -l
docker container ls -l --all
docker container rm [containerID]
docker export [OPTIONS] CONTAINER
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
这里镜像可以简单粗暴的理解为系统安装包,而容器可以理解为虚拟系统。
容器是可以导入和导出的,也就是说配置好了一个自己满意的容器后可以导出,之后每次需要干净的新系统环境之后都可以导入这个,就有一个符合自己需要的干净系统了。
docker 的启动使用 docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
命令,例如:
docker run -it -p 8022:22 --ipc host --name docker_example --gpus all -v ~/work:/work tensorflow/tensorflow:latest-gpu-py3-jupyter /bin/bash
docker 的镜像为了减小体积会精简掉很多内容,比如刚刚这个机遇 Ubuntu 的 tensorflow/tensorflow 就没有 vim、locate、man手册等等,有需要的可以自行安装。
docker 容器启动后可以使用exit退出,而如果使用 -d 模式的话会将 docker 放在后台,此时可以通过 docker attach command 进入容器。
docker 容器关闭后,可以使用 Usage: docker start [OPTIONS] CONTAINER [CONTAINER...]
命令启动容器,此时不能再用 docker run。
nvidia-docker 的安装使用说明中还出现了 -rm 参数,此参数默认则为 false,当使用此参数时会在退出容器时自动清理容器。
如果在 docker 的使用时遇到了用户问题,还可以考虑在 docker run 的时候增加 -u 参数设置登录用户。
如果想修改已有容器的部分参数(如 -v 的目录映射),可以参考 《docker-修改容器的挂载目录三种方式》进行修改。
需要注意 :当 attach 到 docker 服务后,看到的输出是同样的,如果需要同时开启多个窗口可以考虑:
以 TensorFlow 为例,参考 TensorFlow Docker
先抄下介绍:
Docker 使用容器创建虚拟环境,以便将 TensorFlow 安装与系统的其余部分隔离开来。TensorFlow 程序在此虚拟环境中运行,该环境能够与其主机共享资源(访问目录、使用 GPU、连接到互联网等)。系统会针对每个版本测试 TensorFlow Docker 映像。
Docker 是在 Linux 上启用 TensorFlow GPU 支持的最简单方法,因为只需在主机上安装 NVIDIA® GPU 驱动程序(无需安装 NVIDIA® CUDA® 工具包)
可以看出 TensorFlow 官方还是很支持使用 docker 方法的,官方也会发布每个版本经测试的 TensorFlow Docker 镜像,而且 docker 是 Linux 上启用 TensorFlow GPU 支持的最简单方法,直接使用官方打好的镜像,避免我们这些渣渣到处去提“tensorflow gpu 如何配置”这种低级问题。
TensorFlow Docker 要求在本地主机上安装 Docker,如果需要在 Linux 上启用 GPU 支持,请安装 nvidia-docker
注意:要在没有 sudo 的情况下运行 docker 命令,请创建 docker 组并添加用户。有关详情,请参阅针对 Linux 的安装后步骤。
是使用 TensorFlow Docker 首先要拉取官方镜像,镜像位于 tensorflow/tensorflow,是基于 Ubuntu 的,映像版本按照以下格式进行标记:
每个基本标记都有用于添加或更改功能的变体:
例如 tensorflow/tensorflow:latest-gpu-py3-jupyter
表示最新版(latest)、带GPU支持(-gpu)、基于Python3(-py3)、含 jupyter (-jupyter)
需要注意的是并非所有版本都包含这些,例如 tensorflow 1.12.0 并没有 jupyter 项,具体镜像可以通过 tensorflow/tensorflow/tags 搜索查询
选定好版本后可以通过docker pull [OPTIONS] NAME[:TAG|@DIGEST]
拉取镜像到本地
docker pull tensorflow/tensorflow:latest-gpu-jupyter
即为拉取基于py2的最新版TensorFlow,带 gpu 和 jupyterdocker run
命令时如果本地没有对应镜像则会自动拉取拉取镜像(或者不拉取也行)后,可以通过上文介绍过的 docker run
命令启动容器
TensorFlow:docker run -it tensorflow/tensorflow bash
,其余容器名称、目录映射、端口映射等设置项可以参考上文--gpus all
命令,其中 all 为使用所有 gpu,具体设置参考 《Usage》习惯使用 jupyter notebook 的同学可以参考官方设置启用 jupyter notebook,例如
docker run -it -p 8888:8888 tensorflow/tensorflow:latest-gpu-jupyter
但我不习惯使用 jupyter notebook,所以没有认真测试过是否好用。
此部分参考 [1] 以及 [2],之所以配置 ssh 是为了能够在启动容器后可通过 ssh 连接,也是为了后续能够通过 VSCode 进行远程连接。
然而似乎在 docker 中不应该启用 ssh 服务,并且 VSCode 似乎也是可以直接通过 docker 容器远程连接[3],因此此处只是介绍方法,具体如何使用还需自行判断。
apt update
apt install -y openssh-server
mkdir /var/run/sshd
echo 'root:passwd' | mypasswd
sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
sed 's@sessions*requireds*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
echo "export VISIBLE=now" >> /etc/profile
service ssh restart
此处第 4 行设置了容器的 root 用户登录密码为 mypasswd,第 5 行修改了 ssh 的设置为可以通过密码登录。
需要注意的是,根据 [2] 的回复中的记录看,似乎第 5 行可能有问题,导致密码依旧无法登录,如有问题可以自行查阅 ssh 配置文档进行修改。
当然此处更推荐的方式是参考 [4] 中的方式生成 ssh-key,并将 ssh-key 加入容器系统的 /root/.ssh/authorized_keys
,这样可以实现免密登录,减少了每次登录输入密码的麻烦。
还需要注意的是每次停用 docker 的时候 ssh 服务会关闭,再次使用时候需要再次启用 ssh 服务,这样也间接避免了容器内 ssh 服务在不使用时开启的问题。
Oh-My-Zsh 是一款基于 zsh 的命令行工具,可以说是一种生活方式,而我大概更多是因为莫名的觉得 oh-my-zsh看起来有点像orz(笑)。
不过也有很多人不习惯使用 zsh,而是更喜欢系统的 bash,因此此处只是介绍下 oh-my-zsh 的配置,使用与否自行决定。
oh-my-zsh 的官方网站是[ohmyzsh],使用文档可以参考 wiki。
首先需要 安装zsh。并将 zsh 设置为默认shell,此处可能会设置失败,参考:zsh default without chsh
之后需要安装 ohmyzsh,需要注意的是必须已安装 curl 或者 wget 以及 git,安装方式由以下三种:
via curl:sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
via wget:sh -c "$(wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
curl -Lo install.sh https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh && sh install.sh
安装好 ohmyzsh 之后可以设置下主题和插件
插件比较值得推荐的是 zsh-syntax-highlighting,安装方式参考 How to install,在 ohmyzsh 中可以直接通过命令安装
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
安装插件之后运行 plugins=( [plugins...] zsh-syntax-highlighting)
启动插件。
ohmyzsh的插件和主题及按键映射等配置项都在 ~/.zshrc 中,其中
ZSH_THEME="ys"
:设置主题,主题可以参考 Themesplugins=(git z zsh-syntax-highlighting)
:用来设置启用的插件,插件可以参考 Plugins上文已经介绍了如何使用 docker 创建一个属于自己的丹炉,那么下一步就是使用这个丹炉炼丹了。习惯使用 jupyter notebook 的同学可以参考官方设置启用 jupyter notebook,或者参考[5],但我没有具体测试过。接下来要参考 [3] 及 [4] 中方法介绍 VSCode 远程炼丹方法。
PS:以下介绍实际上并不基于 docker,而是在 docker 容器内启用 ssh 服务后的 VSCode 的通用方法。也就是说对于非 docker 情况,只要能用 ssh 连接则是通用的。
PPS:貌似这种用 ssh 连接 docker 容器的方式比较不符合 docker 理念,而 VSCode Remote 提供了直连容器的方法 [Developing inside a Container],但我目前还没研究明白…有精通此道的同学请指点下我,或者等我自行领悟后也有可能更新下此文。
VSCode 作为宇宙第一IDE—— Visual Studio 的兄弟,目标自然是宇宙第一编辑器(Vim、Emacs:嗯?)。
从多年前刚刚发布时不支持插件的版本开始,VSCode 的市场份额在逐步扩张。
关于 VSCode 能够成功的原因可以参考下:Visual Studio Code 可以翻盘成功主要是因为什么?我这里说明下我选择 VSCode 的原因吧。
如果有人问写 Python 最好的工具是什么,那我一定毫不犹豫的说 Pycharm;而 C++ IDE 则必须是前文提到的 VS。但是很多时候我要面对的不仅仅是 Python,作为一个打杂的,C++、Python、Shell 都是常用的,在一些情况下 Java、Perl 也是要会一点的,偶尔做个 Demo 的话 Html 也是需要了解一二的,在更偶尔的情况下世界上最好的语言 PHP 也要能看能改的,面对这种复杂环境,我觉得还是 VSCode 这种能试用不同场景的编辑器比较符合我的需求。
还有就是 VSCode 还能远程连接服务器,头文件依赖库都是直接基于服务器内环境,跳转、查阅都方便。当然 Pycharm 和 VS 也提供远程开发——但那不是收费的嘛。
不过 VSCode 也存在它的局限性,毕竟有些时候临时使用线上机器或者他人机器,不可能在每台机器上都配置VSCode,这时还是要靠 Vim 的。总体而言很多开发工作是可以转移到 VSCode 进行的。
没啥好说的,看看 官方网站 。而 VSCode 的常用介绍及配置介绍可以参考下 [6] 和 [7] 及其他网上能搜到的相关文章。这里说几个我觉得需要注意的地方
VSCode 的 Remote Development 配置可以参考官方文旦 [Remote development over SSH],也可以参考 [4],其中比较需要注意的地方就是 ssh-key 的生成,当然这里 ssh-key 的应用场景不仅仅是 VSCode。
在按照上文提到的方式在 docker 容器中启用 ssh 服务后,自然也可以通过 VSCode 的 Remote Development 以 SSH 方式访问 docker 容器,需要注意的一点是此时 VSCode 的 ssh 配置时要增加 Port 参数,例如
Host TestServer
HostName ${
ip}
User root
Port 8022
其中 ${ip} 为远程服务器 ip 地址, Port 则为之前在使用 'docker run' 命令时使用'-p'参数设置的转发端口。也就是说使用 8022 端口连接,而这个连接会转发到容器的 22 号端口(默认ssh端口)。因此如果在 'docker run' 时没指定端口转发的话,就不能以此方式连接容器。
VSCode 的一个强大之处就在于丰富的扩展——特别是一些官方支持的扩展。前文提到的 Remote Development 就是微软官方提供的远程开发扩展集合。
网络上现在也有很多 VSCode 扩展的推荐,但普遍是前端偏多,毕竟 VSCode 实属前端神器。而以下会介绍一些我日常使用的扩展,我的目标是把 VSCode 打造成打杂神器。
VSCode 的扩展是有本地安装和需要远程安装两种情况的,本地安装的扩展是指在使用 VSCode Remote Development 时不需要在服务器再安装一遍的,而远程安装的是指需要在服务器再次安装的,其中远程安装的扩展也可以使用本地的全局配置。
"python.formatting.provider": "autopep8"
, 设置,还支持 yapf 和 blacktodo-tree.filtering.excludeGlobs
把数据文件排除以上用了 8000 来字介绍了一些 docker + vscode 的配置,然而大家可以我介绍的详细程度看出来:没错,我就是来吹 VSCode 的(笑)。
言归正传,其实除了我这里提到的 Docker 的方法外,其实 Python 的虚拟环境也是个很好的隔离选择,可以用来配置不同版本的 python 解释器。
最后祝大家都能配置好自己炼丹炉,不受别人的炉子干扰,也不干扰别人的炉子…