index - nevermosby/ytdl-bypy GitHub Wiki
The Whale Pirate团队, 热衷Docker技术及应用的研究与探索。
开发者
作为程序员,常常会通过各种途径观看YouTube视频,了解最新行业资讯,或学习新技术,可是免不了受到些限制,比如
- 看到一个挺好的YouTube视频,可是没有机会全部看完
- 手机端无法便捷流畅地观看YouTube视频
- 等等。。。
我们开发这个项目正是为了解决这些问题。基于hubot,你只要把你想看的YouTube视频网址以聊天的形式发给它,你就可以不用管了。hubot会帮你:
- 下载指定视频
- 把下载好的视频上传保存到国内网盘。
- 视频下载和上传完成后,hubot会推送通知给你,追踪视频下载情况。
这样的过程更便捷、更智能,分分钟便可完成,借助网盘的客户端,任何设备便可随时播放查看。
-
整体设计
- 在**
首都在线
上,创建两个Linux VM,一个在美国地区,另一个在国内(我们使用了北京),并且把它们置于首都在线
提供的GPN
**直连网络里。 - 在美国地区的VM上下载YouTube视频,通过Docker和**
GPN
**连接北京地区的VM,上传下载好的视频到国内网盘,这样就可以随时随地观看了。 - 整个过程,通过hubot在flowdock上,浏览器和手机客户端都可以触发,支持并发请求。
- 在**
-
下载YouTube视频
选取了youtube-dl作为下载视频的工具,只要传入YouTube视频地址,即可下载到MP4格式的视频文件。
把这个下载过程Docker化,即写了相应的Dockerfile,bulid出相应的image,包含了youtube-dl,直接可以调用。为了能够正常下载,使用在美国地区的VM,运行
Docker Run
这个image。 -
上传YouTube视频到国内网盘
有了视频源文件,想要随时随地观看,比较好的方法就是保存在网盘里,最好是国内的,这样能保证下载速度。这次选择了百度网盘(容量大,比较稳定),配合bypy这个python客户端,这样能通过编程方式上传视频到百度盘,使自动化整个上传过程变成可能。
也把这个上传过程Docker化,写了相应的Dockerfile,build出相应的image,包含了bypy工具,就可以直接使用。为了能够获取更好的上传速度,使用在北京地区的VM,运行
Docker Run
这个image。 -
通过Docker Machine/Swarm建立跨host的通信
Docker在1.9之后,重新实现了network组件,提供了Overlay的网络模式,配合Docker Swarm可以实现跨host的通信,详情参见link。
为了方便管理Docker Swarm,我们使用Docker Machine来创建Docker Swarm,即直接在首都在线提供的VM上,使用Docker Machine创建Docker Host(安装Docker Engine,以及配置它使用TLS验证来运行Docker Engine,这样,可以远程访问这台VM上的Docker Engine)以及Docker Swarm。
将上面两个Docker Container(下载和上传)配置在通过一个Overlay的network下,这样他们就可以在service层互相通信了。
-
通过Docker+NFS实现跨host数据共享
我们需要将下载好的视频上传,就需要打通部署在不同host上,负责下载的Docker Container,和负责上传的Docker Container对于视频数据共享访问。我们选取了NFS(Network File System)这个比较成熟的网络共享的solution,并用Docker Data Container进行封装,实现了跨host的Docker Container级别的数据共享。
-
通过hubot接受请求
以上为后端的实现,为了方便地触发下载-上传任务,我们选择使用hubot来接受前台请求,用户可以直接在具有hubot的聊天协作平台(我们使用了flowdock)上,以发消息的方式提交请求。我们使用docker+nodejs搭建了一个web server接受请求并触发下载-上传任务。
- 配置Docker Machine和Docker Swarm
- Docker Swarm Master
- Docker Swarm Agent
- Key-Value Store
- 在负责下载的Docker Host上
- 创建Docker Data Container
- 运行Docker NFS Server Container
- 运行Docker化hubot Container
- 准备好负责下载视频的Docker Image
- 在负责上传的Docker Host上
- 运行Docker Video Track Container来保存视频信息,推送给hubot所在的协作平台
- nodejs web server
- mongodb
- 运行Docker Video Download-Upload handler Container来处理下载和上传的请求
- nodejs web server
- 准备好负责上传视频的Docker Image
- 运行Docker Video Track Container来保存视频信息,推送给hubot所在的协作平台
- 完成配置后,就可以使用
- 负责下载的Docker Host
- 负责上传的Docker Host
- 负责下载的Docker Host
-
以一定格式发送消息给hubot
@<your hubot name>, gm <youtube video url> <your comments>
-
下载完成后,hubot将会发消息给请求者,告知下载完成,例如
{ "DownloadResult":"201-Request has been created", "Message":"" }
Hubot交互实例截图:
-
下载,上传整个流程结束后,hubot推送一条关于下载视频的消息,包括url,标题,文件大小,保存位置等。截图如下:
-
使用Docker Machine整合**
首都在线
**GIC的虚拟主机- 痛点
- GIC没有API可以直接创建虚拟主机,无法自动化
- GIC不能作为Cloud Privider被Docker Machine直接作为Driver使用
- 解决
-
手动创建虚拟主机,并记下公网IP地址。
-
刚开始想使用Docker Machine的
Adding a host without a driver
模式,通过以下命令添加已有docker engine的虚拟主机:# 传入连接远程Docker engine的TLS Credential # 必须指定`-d "none"`,否则不能添加成功 # 你需要将远程的Docker engine的TLS Credential \ # 手动copy到运行docker machine命令的机器上,非常麻烦!!! docker-machine \ --tls-ca-cert /root/twp001/ca.pem \ --tls-client-cert /root/twp001/server.pem \ --tls-client-key /root/twp001/server-key.pem \ create -d "none" --url=tcp://<ip-address>:2376 twp001
后来,使用了Docker Machine的
Generic Driver
,来直接连接虚拟主机,并安装配置Docker engine:# 你只需要提供连接远程机器的ssh credential \ # 就可以创建出一个完整的docker host,适用于GIC所有Linux主机。 docker-machine \ create -d generic \ --generic-ip-address <ip-of-remote-vm> \ --generic-ssh-user root \ --generic-ssh-key ~/key/gic-twp twp001
这样,就可以直接通过Docker Machine来管理多个Docker Host了。
-
- 痛点
-
使用Docker + Overlay + NFS实现跨主机数据共享
- 痛点
- Docker Data Container无法使用
--volumes-from
+--net
进行跨主机共享 - 目前的Docker Volume Plugin(Flocker或者Convoy)都需要配合额外的存储平台(Amazon S3或者Openstack Cinder)进行转存,引入后,复杂度较高。
- Docker Data Container无法使用
- 解决
选取成熟、简单的
NFS(Network File System)
来共享数据。具体就是:- 在负责下载的Docker Host上创建一个Docker Data Container,并映射到host上的一个目录,这是下载完视频的存储路径。
-
命令:
docker create \ -v /home/docker/shared-vol:/shared-data \ --name shared-data-vol busybox
-
- 在负责下载的Docker Host上运行一个Docker化的NFS server,并且:
-
使用
--volumes-from
将刚刚创建的Data Container加载进来,这样,数据文件可被NFS Server Container访问,并使用NFS mount那个存储路径 -
使用
--net
将NFS Server Container加入到跨主机网络中 -
命令:
docker run -d --name nfs-server-david \ --privileged --net=my-net \ --volumes-from shared-data-vol \ david/nfs-server /shared-data
-
- 在负责上传的Docker Host上按需运行一个Docker化的NFS client,并且:
-
使用
--net
将NFS Client Container加入到跨主机网站中,这样,无须知道NFS Server的具体IP地址,只要使用NFS Server的Container名字就可以通信。 -
命令:
docker run --privileged --net=my-net \ -e NFS_SERVER=nfs-server-david \ -e NFS_SRC=/shared-data \ -e NFS_TARGET=/shared-data \ david/youknownothing-upload
-
- 因为两台Docker Host通过**
GPN
**直连了起来,所以整个传输性能相当出色。
- 在负责下载的Docker Host上创建一个Docker Data Container,并映射到host上的一个目录,这是下载完视频的存储路径。
- 痛点
-
使用Docker+nodejs+dockerode实现自动化下载和上传
- 痛点
- 使用Docker命令行运行下载container,无法得知完成状态。这样,就不能准确地运行上传的container
- Hubot如何自动化触发下载-上传任务
- 解决
使用编程的方式(Docker Remote API)来启动负责上传和下载的containers。由于hubot是nodejs实现的,为了交互方便,选取了dockerode这个nodejs版的Docker SDK。
-
使用dockerode中docker.run 由于需要在docker run的同时,传入各种参数,如环境变量、网络、volumes等,所以选取docker.run来模拟,它几乎提供了所有Docker remote API提供的功能。
-
命令:
localDocker.run('david/youknownothing-upload', ["bash", "-c", uploadCmd], uploadLogStream, { "Env" : [ "NFS_SERVER=nfs-server", "NFS_SRC=/shared-data", "NFS_TARGET=/shared-data" ], "HostConfig" : { "Privileged" : true, "NetworkMode" : "twp", "Binds" : ["/root/.bypy/bypy.json:/root/.bypy/bypy.json:ro"] } }, {}, function (err, data, container) { if (data.StatusCode != 0) { console.error("Failed to upload the target video: " + targetUrl); } else { // do the real stuff } });
-
- 痛点
- 修复Bug
- 获取video size在某些情况下会出错,可能是curl超时导致
- 把Nodejs Express转成Nodejs Koajs
- 改进Nodejs里的异步方法(callback)调用模式
- 支持更多视频链接的下载
- 支持更多网盘的上传