Ubuntu18.04与deepin+nvidia-docker的构建与踩坑+puppeteer在docker中的使用

写在前面的废话

        首先说什么docker,之前我啥也不知道,大概了解,就是一个集成环境,然后可以带着这个跨越各种平台什么的。就这几天的使用来看,差不多是的吧,在使用上,感觉确实是一个带系统的集成环境,基本上和主机隔离开了,在我看来,就是一个虚拟机,然后里面可以装各种环境,然后还可以复制带走,他们之间的区别不太清楚,感觉虚拟机更方便才是,docker每次修改之后,如果不发布的话,那就没有了哟。
        再说明一下,其实就docker的情况,我原本就很奇怪,cuda怎么装,最后发现,不用装,这里我发了一个傻,后面再提。反正就是在docker hub上,nvidia有发布装好cuda的镜像,pull下来,再自己折腾环境就可以了。

 

我的具体需求

         我这里的需求是,有一个任务,然后很多台电脑都需要使用,但是装环境很麻烦,主要就是,原本我都装好所有环境了,但是现在这个任务执行很慢,通过查询发现,有一个模型的后处理,作者有提供c++和python两个版本,但是c++版本需要自己编译opencv,这个就略微的有点麻烦,在装完一台电脑之后,拒绝再在其他电脑上折腾了,此时老板跟我说,整个docker吧,你应该去整个docker。
        

docker安装

        这边电脑分了两个平台三个系统,一个个来,从Ubuntu开始,在开发者中Ubuntu使用率应该很高,网上资料一查一大堆,不过很多重复的,反正以下是我收集整理使用的。

sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get -y update
sudo apt-get -y install docker-ce
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update
sudo apt-get install -y nvidia-docker2

        我在第一台电脑上是一条一条输入的,后来可行后,就直接用一个sh脚本直接一撸到底,这里我用的阿里云的地址,很多资料用的是官方的,由于担心国内网络环境,就还是用阿里云的吧。

        稍微解释一下,也是几乎所有资料说的,安装的第一件事是删除旧版本,如果有的话

sudo apt-get remove docker docker-engine docker.io

        然后第二件事是,安装显卡驱动,deb安装很方便的,而且docker其实可以很方便的跑程序,本就可以不装环境了,那么就直接用系统自带的软件更新器,找到附加驱动安装好了。

        然后再上面那一大串,还需要注意的是,docker没有必要装最新的,有特殊需要的,就记得指定版本;nvidia-docker是2,不要掉了

这里可以稍微看一下终端消息,没有报错消息的话,就成功了,当然也可以按照常规方案测试一下

docker run hello-world
docker run --runtime=nvidia --rm nvidia/cuda:9.0-base nvidia-smi

第一条是测试docker,第二条是测试nvidia-docker的,尤其是第二条出现了显卡信息,就完成了。记得前面加sudo。

顺便提一下,我这边打算装的是cuda10.1,但是显卡驱动是410的,后来提示驱动版本低了,所以一开始就装高一点的版本吧。

环境搭建

         nvidia-docker是一个命令,感觉和docker差不多。首先要拉取一个镜像,在这个操作之前,建议做两个操作

        1.首先是解决权限问题

sudo groupadd docker
sudo gpasswd -a ${USER} docker
sudo service docker restart
newgrp - docker

基本意思就是,把当前用户加入docker组中,这样以后使用的时候就不用加sudo了。其中最后一步我都没有做,直接重启了。

稍微说一下,service docker restart是重启docker,还可以用systemctl restart docker,两者有没有区别不知道,当成一个小知识点吧。

        2.接下来,处理一下磁盘占用,docker的默认位置在/var/lib/docker中,如果你的磁盘空间不够的话,就转移一个位置,再在原地创建一个链接

sudo mv /var/lib/docker /media/PATH/data/dockerVar
sudo ln -s /media/PATH/data/dockerVar/docker /var/lib/docker

上面的PATH是各自自己的路径,就是这个原理,知道就行了。一开始就做,会比较快,等已经有一些镜像了,再做,就比较慢了。

        3.其实还有一个,换成阿里云的源,在/etc/docker/daemon.json里面的{}中,增加或者修改这一项——"registry-mirrors": ["https://fird1mfg.mirror.aliyuncs.com"]——注意是json的格式,所以别忘了加一个逗号。

在这两个都做好后,可以去DockerHub上搜索一下镜像,只是有的时候可能由于网络原因,会比较慢,可以用用命令docker search,不过这个搜到的,描述太长就变省略号了,由于我需要装好opencv的,好不容易找到一个opencv3.4.2的,结果用网页搜索了下,发现被省略的部分写了,是基于py2.7的,浪费表情。

稍微解释一下,镜像一般分两部分,一般前部分就是这个镜像的简单描述,然后后面是版本(tag)以冒号隔开,如nvidia/cuda:cuda9.0-base。如果你打算使用cuda的话,建议就不要下别的,就找cuda的,我不知道能不能自己装cuda呢,不要冒险,我都还在docker里面编译opencv呢,起码这个是绝对可行的,比装cuda好一点吧。

搜索nvidia,会出现类似下面,这些是镜像,点进去会出现其所支持的tag

nvidia搜索结果

点击nvidia/cuda,其实里面的内容已经写得比较清晰了,基本都在里面——nvidia/cuda的所有tag——就懒得写了,我最后选的是 10.1-cudnn7-devel-ubuntu18.04

直接

docker pull nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04

然后等着就可以了。

稍微介绍一下docker(nvidia-docker)的参数

我们下载下来的是一个镜像,我就是理解成一个类,然后我们需要以此创建一个容器(实例)

普通的创建方法是

nvidia-docker run -it IMAGES /bin/bash

这个就是会打开这个镜像,具体解释省了,反正就是-it不要省略,最后一个/bin/bash,可以理解成打开这个镜像后需要做什么操作,然后你可以可以加一个-d后台操作,就是后台默默运行,然后把bash换成你需要他执行的命令,不过我用来跑程序什么的,就是需要终端的。

  • --name 给创建的容器命名,如果不自己命令,会随机生成一个名字,因为在生产环境中,可能有很多个容器,做不同的操作,但是又不好区分,此时可以自己命名,但是这个名字除此之外,貌似没有别的作用了,所以我用不着。
  • -v 本地位置映射,基本格式是"localPath:DstPath",前者是主机的路径,注意,是需要绝对路径,且里面不要有外部链接,,容器里面,这些链到外部的就断了;后面是容器路径,建议也写绝对路径,如果目录不存在,会自己创建。个人感觉这个非常有用,起码我可以用来传递文件,也可以直接把代码放进去,而且这个路径是实时的,我可以主机修改代码,容器运行;可以写多个-v来映射多个路径;此外,这个参数网上有人做了详细的测试,验证各种情况,有兴趣可以自己看看——linux docker 目录挂载映射
  • -p ip端口映射,这个我理解不深,原本是想用来主机ssh docker的,后来发现似乎不用,后面会有说明。

这里主要参考了两篇帖子

Docker 镜像使用,这一个主要是讲了docker的一些使用方法,很实用,参数介绍很比较好,然后他有似乎是一整个教程,有上一篇下一篇,估计很有用,不过我只看了这一个

Docker & Nvidia-docker 镜像基础操作,这个前面部分讲了怎么安装docker,跳过之后,后面有一些用法,比如怎么导入导出

 

后面是踩坑,初次进去,发现目录下的中文名字文件显示的是一串数字,大概是没有中文支持,具体探究就免了,直接上解决办法

nvidia-docker run -it --name test -p 1020:22 -v /LOCAL:/DST IMAGE:TAG env LANG=C.UTF-8 /bin/bash

差不多描述了下各种参数的用法了,后面加上一个环境就可以了,再进去就发现正常了。

此时使用docker ps -a可以看到所有的容器,是不是有很多呢,每次进去就会创建一个新的容器,所以之前做的修改就木有了,且感觉很浪费,删除容器的命令是docker rm ID,可以写多个ID,以空格隔开,但是状态是up的容器不可以删除,关闭就是docker stop ID。此外也可以进入已有的容器,如果是关闭状态的容器,先要用docker start ID打开,然后

nvidia-docker exec -it ID /bin/bash

基本上和run差不多,就是换成了exec,此外,这个exec至少需要两个参数,也就是ID和命令(如/bin/bash),不多说了。

然后在里面可以各种装环境,和正常电脑一样的,除了没有界面外,最后测试完毕后,接下来就要上传发布了,不然就白做了

nvidia-docker commit -m="update" -a="daniel" ID IMAGE:TAG

 稍微说明下,先exit退出当前容器,记住他的ID,然后用这个命令把这个容器发布,变成镜像,其中-m就是写一下更新内容啥的,-a是作者名,ID是该容器名字,后面是生成的镜像的名字和tag,自定义的。这个发布不是上传到hub上哈,别想太多,可以理解为固定住这个容器,这个操作比较需要磁盘空间,注意前面讲的,替换一下默认位置会好一点哟。当然,不做这步也是可以的不过就只能自己这台电脑使用,还需要注意不要不小心删除了这个容器,不然就凉了。生成镜像之后,之前的原始镜像就没啥用了,删了吧,删除镜像命令

docker rmi ID or IMAGES:TAG

删除镜像,可以通过镜像ID来删,不过似乎有的时候会报错啥的,就可以指定名称和版本号来删。

现在需要转移镜像了,要先导出

nvidia-docker save -o ./IMAGE.tar  IMAGE:TAG
nvidia-docker load < ./IMAGE.tar

第一条是将一个镜像导出成一个tar包,名称自定义,然后生成后可以将其转移到其他电脑上,再用load导入,"<"这个别忘了。

 基本上就是这样了

 

        但是还没完,此时提到主机ssh到docker上面,我试了很多办法,网上都是说端口映射,然后就很简单的,我怎么都搞不定,这里我忽略了一点,docker敲ifconfig的时候,提示没有这个命令,然后网上说先apt install openssh-server,然后我也没看,敲了,发现没有下载,以为自带了,其实自带的是openssh-client,后来多方找原因,比如service ssh restart会提示没有ssh,直接ssh restart会提示没有ip或者hostname,最后发现原来是没有apt update,做了后可以顺利安装openssh-server,service ssh restart也可以进行了,我又发现没有ifconfig,也没ping,发现这个需要apt安装

apt-get install net-tools
###   ifconfig
apt-get install iputils-ping
###  ping
apt-get install iproute2
####  ip

不过我只下了前两个,此时可以查看docker的ip,一般是172.17.0.2,然后

apt install openssh-server

安装ssh之后,还不行,还要修改一下/etc/ssh/sshd_config这个文件,尤其是“PermitRootLogin yes”,这一项设置是否允许root用户登录,docker中默认就是root用户嘛,当然是允许啦,这样就可以了,网上还有人说要“UsePAM no”,这一项我没管。

ssh连接docker就这么简单,简直是,为啥网上都不写这种操作,要我找那么复杂的端口映射,根本看不懂,而且,因为我映射了端口后的容器,又上传成镜像,结果这个镜像的所有容器都带有这个映射,而且是我每次尝试的端口都有,这就让我强迫症犯了,也不知道怎么删除,最后查到修改docker容器端口映射的方法这个,直接清空那几项就可以了。

但是ssh -X 依然不能得到docker里面的图像数据,如有相关的显示操作,比如"opencv.imshow"之类的会报:cannot connect to X server这样的错误,我先看到这个帖子在Docker中使用GUI环境,解决cannot connect to X server问题,也就是提到ssh -X,然后就有了上面一系列操作,但是ssh可以连接之后,加了-X操作,也没有用,事情本就告一段落了,然后今天又查了下,综合了好几个帖子,再在/etc/ssh/sshd_config中,设置这几项,“X11Forwarding yes”,“X11DisplayOffset 10”,“X11UseLocalhost no”和“AllowTcpForwarding yes”顺便把上面的“UsePAM no”给补上。这里需要注意的是,不要直接添加,查找一下这几项,把原始的注释掉再加哦。然后就OK了,能顺利打开图像相关的操作了。

最后补一个,网上都说docker中的容器的日志占用非常大,而且会越来越大,然后也查了个限制的办法,Docker 清理容器 log 日志,他写的很清楚,怎么找到日志文件,然后怎么清空,怎么做限制。

 

Deepin:

        这个系统不能说不好用,他就是更注重的是面向普通使用用户,但我们开发者嘛,有的操作,这个系统就不让用,比如cuda安装,本来发现在Ubuntu上,用deb安装cuda非常方便傻瓜,但是deepin他不可以,要一些稍微复杂一些的方法。

        上面ubuntu的安装docker的代码,deepin不能完全照搬,虽然最后还是装好了,但是觉得,巨坑,差点换系统了。

虽然deepin的坑是满满的,不过网上还是查的到资源的,不过感觉比较分散,有的提供的方法解决不了问题,我这边就我的情况,整理一下。

我这边的系统是15.11的,前文也提到装cuda就比较坑,然后出现一个问题,也不知道是不是因为强行装的原因,在一些弹出式的窗口的时候,比如iptux,还有解压的窗口的时候,整个屏幕会一直黑屏闪烁,但是转移焦点到其他地方,就恢复正常了,在装这次docker的时候居然一并解决了,以下慢慢道来。

首先是装docker,基本命令与上面一致就是要注意有几项;

第三条执行失败,所以我就直接打开/etc/apt/source.list,写入"deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic stable"

然后在装docker-ce的时候,报错,错误内容大概是containerd.io 的什么版本问题,然后如果再安装这个,又提示新的东西没有安装,然后通过install -f也没啥用,后来查到可以这样,

使用apt-cache madison docker-ce来查看可以安装的最新版本,然后找一个版本指定该版本安装就完了

sudo apt-get install docker-ce=18.06.3~ce~3-0~ubuntu

然后接下来

curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/ubuntu16.04/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

这两个与上面的不同,这里用的ubuntu16.04的,为啥不用18.04,我也不知道,查到的别人用的就是16,我也不敢试。然后就可以

sudo apt-get update
sudo apt-get install -y nvidia-docker2
sudo pkill -SIGHUP dockerd

至此,nvidia-docker算是装好了,但是我试了下,比如用cuda9.0base试了下nvidia-smi,会报错,此时还是有点慌的,网上查了下,先装一些工具、库之类的

sudo apt-get install nvidia-opencl-common libnvidia-encode1 libnvidia-fbc1 libnvidia-ifr1 libgles1-nvidia libcuda1 nvidia-smi

我做了,但是弹出一个图形界面,说是nvidia-installer以前通过.run安装过,有残留之类的,问我要不要先卸载,此时如果点击要,则该终端卡死,点否,则以后用apt的任何东西,都会弹出这个,稍微看了下提示,貌似是不能再图形界面做这个操作,反正最后我也没有做,看他说可以直接delete,我就

sudo apt-get --purge remove nvidia-installer*

此时会让卸载另外一个东西,不记得了,反正就是恰好解决了前面说的闪屏的问题,可喜可贺。

至于上面提的nvidia-docker疑似不能用的问题,还是上面那个帖子,他说的修改/etc/nvidia-container-runtime/config.toml, 将ldconfig="@/sbin/ldconfig.real"注释掉

这个就可以了,不过貌似不做也可以,还是可以导入镜像,然后创建容器,但是好像使用会有问题,还是要做

上面提到的帖子在这,大家可以看看deepin 15.8 安装nvidia-docker2,我只做了那两项。

然后就比较正常的可以创建容器,在里面玩了。

Puppeteer在Docker上踩坑

        由于镜像是之前ubuntu上创建好了并且可以直接使用的,本以为这边直接用就行了,但是结果并不如此。这从头开始说。以下没有特别说明,都是在ubuntu的docker中,deepin中的会专门说明。

        puppeteer是啥就多说了,在docker里面运行,最大的坑有两个,一个是他的依赖环境不对,我这边最开始在本地运行的时候不觉得,因为当时的系统装好后第一件事就是装一个chrome浏览器嘛,但是在docker那么纯净的环境里,啥都没,依赖自己安装还是比较坑的,这里查到一个命令,可以查到缺少所有的依赖库

ldd node_modules/puppeteer/.local-chromium/linux-641577/chrome-linux/chrome | grep not

这里要找到你自己对应的那个版本,不过自己装还是有点麻烦的,一定要装的话,有个窍门,基本上直接apt install就可以,但是其名字应该是,比如libgbm.so.1,那么就应该是apt install libgbm1;

这里参考的资料就有好几个:

puppeteer 在 docker 中应用出现的问题,这个其实就是解决了我的依赖问题,而且虽然他有提出去Git看官方的Troubleshooting,不过我还是直接看他的提炼内容,通过

apt-get update && \
    apt-get -y install xvfb gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 \
      libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 \
      libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 \
      libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 \
      libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget && \
    rm -rf /var/lib/apt/lists/*

通过这样解决了,但是后面是我经历最烦的过程,也是感觉最坑的,docker默认是以root用户进去的,然后root用户不能直接调用chrome,然后当时我加了--no-sandbox还是不行,官方的解决方法是,新建一个用户,但是新建一个用户的话,我的之前的环境就不好搞了 ,比如anaconda,然后各种查,这里查看的太多了,我自己也乱了,其实就是还缺少一个参数——“--disable-dev-shm-usage”,也就是

this.browser = await puppeteer.launch({
  executablePath: puppeteer.executablePath(),
  args: ['--no-sandbox', '--disable-dev-shm-usage'],
});

puppeteer.executablePath()这个会返回chrome的路径,还是很赞的。然后其实这个帖子一共提出三个问题,我只看了前两个,第三个没看,而这第三个就是字体问题,docker中原生没有带中文字体,不后来仔细看了下,他的方法要下载字体包,字体包在哪下也没说,反正我自己解决办法是把本机的字体移到映射的目录内,然后在docker中再移到相应的位置,完美解决。

至此在ubuntu上的puppeteer就可以运行了,当时其实主要只参考了这一个帖子,下面的都是在deepin上发现不能用的时候查到的,也提一下

截图的诱惑:Docker部署Puppeteer项目,这个写的很好,只是很长,要翻到很下面才有一些踩坑,最重要的是,我是才发现的,所这一篇对我的最大贡献就是提供了下面这个链接,然后这个真的写的很好了,可惜我当初没有看完。

爬虫利器 Puppeteer 实战,这个是在上一个链接中找到的,他对我最大的好处就是,提供了一个cnpm,然后可以顺利下载puppeteer,其实我发现node_modules这个是可以移动的,打包之后移到其他电脑,就可以直接使用,就不用重复下载了,那我为什么还要下载,就是他在deepin的这个docker中不知道为啥不能用,会一直等着,直到timeout,后来看他的报错,似乎是说必须要是对应的版本的chrome,算了算了,重新下一个好了吧,结果好像好了,这里还有其他坑,下面再讲。

Puppeteer 截图及相关问题,这个他也是很长,前面都是实例,然后他提到了字体缺失的问题,但是他的解决方法我后来试了,没有用,还是从有用的电脑拷贝出来最靠谱。

上面提到,在deepin的docker中,遇到在ubuntu上没有碰到的,简直是费解到想干脆放弃这个系统吧,本来也是尝鲜的,后来在多次试的时候发现,deepin的docker中不能上网,ping在之前说过已经装好了的,而且这次也不是提示没有这个命令,是提示别的,然后多方尝试后,发现docker容器启动时会报 socket permission denied或者listen tcp port failed 等错误的原因这个帖子,虽然我和他的报错不一样,但是我还是把这个apparmor给卸载了,不过他提到的什么yml,不太懂,也不知道在哪里,怎么改,先算了,反正删了后,网络正常了,我就赶紧重新下载了puppeteer,一试,居然缺个库,就是缺libgbm.so.1,装好后就正常了,此时换回之前的node_modules也是正常的,所以其实就是网络问题吧,大概,被这个apparmor害惨了。

至此,deepin中的docker已经puppeteer也能正常使用了,感觉deepin比ubuntu还要麻烦些,开发不太建议就是了。

 

WIN10的docker也是要装的,不过还开始,以后再补吧!

20200516:今天发现,原来win10不可以安装nvidia-docker,那就没啥意义了,我还是可以直接装cuda来跑深度学习的。不过那我的问题就变成了,要怎么在不安装vs的情况下,编译opencv和使用c++加速,,,后来觉得,还是不要折腾了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值