公司有个项目是运行在Raspberry Pi上面,这个项目涉及到Perl,Python,Java Applet,并且未来Pi的数量可能达到上千个。最近碰到了一样的代码遵循一样的部署脚本,在不同的树莓派上运行竟然到不同的结果。于是也想将Docker应用到树莓派上面去,使用docker主要优点:
1 消除环境差异,程序运行所依赖的环境已经一起打包,随身携带了
2 简化配置,只有docker相关配置,不再需要每个语言单独配置
3 重复利用
4 方便升级,之前有差异时,是重写镜像。。
5 方便管理,可以使用docker已有的工具来管理
6 性能接近原生应用
Raspberry Pi在jessie这个版本就已经支持了docker,检查版本:
1 2 3 4 5 6 | $ lsb_release -da No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU /Linux 8.0 (jessie) Release: 8.0 Codename: jessie |
如果你的版本已经支持,直接执行以下命令就可以了:
1 | curl -sSL https: //get .docker.com | sh |
如果你的版本不支持,你需要升级系统或重新刷镜像,可以采用hypriot
1 2 3 4 5 6 7 8 9 10 11 12 | #下载 wget https: //downloads .hypriot.com /hypriotos-rpi-v1 .0.0.img.zip #解压 unzip hypriotos-rpi-v1.0.0.img.zip #查找 SD card ID lsblk #查找类似/dev/mmcblk0 #弹出SD卡 umount /run/media/mac/8734-1E4C #将镜像写入 SD card sudo dd if =hypriotos-rpi-v1.0.0.img of= /dev/mmcblk0 bs=1m |
然后启动,默认的用户名/密码是pirate/hypriot。
当然也可以采用Debian或者是Alpine Linux来定制(Raspberry Pi仅支持 arm版本的系统,并且只能在arm平台上构建,或者这个)。
运行测试一下:
1 | docker run -d -p 80:80 hypriot /rpi-busybox-httpd |
访问以下树莓派的IP,就会看到一个非常神器的网页,而这个容器仅仅几M。在这里可以看到基于hypriot的好几个镜像,也可以搜索其他的raspberry pi镜像。
现在我们使用hypriot/rpi-python来构建一个使用Python Selenium测试带有Java Applet的网页:
1 2 | docker run -idt -P --name web hypriot /rpi-python docker attach web |
进入到容器里面,执行以下命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | sudo apt-get update #安装openjdk sudo apt-get install openjdk-7-jdk #安装Firefox sudo apt-get install iceweasel #安装Java Applet插件 sudo apt-get install icedtea-7-plugin #安装虚拟桌面 sudo apt-get install xvfb #安装Python包管理工具 sudo apt-get install python-pip #安装selenium sudo pip install selenium #安装Python虚拟桌面库 sudo pip install pyvirtualdisplay |
创建测试test.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from selenium import webdriver from selenium.webdriver.common.keys import Keys import time from pyvirtualdisplay import Display from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.firefox.firefox_binary import FirefoxBinary display = Display(visible = 0 , size = ( 800 , 600 )) display.start() caps = DesiredCapabilities.FIREFOX caps[ "marionette" ] = False #caps["binary"] = "/usr/bin/firefox" firefox_binary = FirefoxBinary( "/usr/bin/firefox" ) fp = webdriver.FirefoxProfile() fp.set_preference( "security.enable_java" , True ) fp.set_preference( "plugin.state.java" , 2 ) driver = webdriver.Firefox(firefox_profile = fp,firefox_binary = firefox_binary) driver.maximize_window() time.sleep( 120 ) mos = driver.find_element_by_class_name( "sectiontitle18" ).find_element_by_tag_name( "span" ).get_attribute( "innerHTML" ) print mos driver.close() display.stop() |
运行测试用例:
1 | python test .py |
如果仅仅是这样子,是行不通的,Java Applet的安全询问弹窗超出了浏览器范围是点击不到的,需要更为强大的组件来做,比如。
这里采用取巧的方法,首先把pyvirtualdisplay相关代码注释掉,在界面上观察具体的执行效果,并点击安全询问,运行通过。然后取消注释,再次运行,就可以了。最后将运行通过的配置文件/root/.icedtea目录拷贝出来,放到其他的树莓派里面就可以了。
如果碰到报错”selenium.common.exceptions.WebDriverException: Can’t load the profile”,通常是说Firefox或selenium版本太低,如果检查都不是,需要修改WebDriver的超时时间
1 | nano /usr/local/lib/python2 .7 /dist-packages/selenium/webdriver/firefox/webdriver .py |
timeout从30秒改为120秒:
1 2 3 4 5 6 7 8 | class WebDriver(RemoteWebDriver): # There is no native event support on Mac NATIVE_EVENTS_ALLOWED = sys.platform ! = "darwin" def __init__( self , firefox_profile = None , firefox_binary = None , timeout = 120 , |
修改为容器后,提交变更:
1 2 3 4 5 | root@black-pearl: /home/pirate # docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 04762770df2d hypriot /rpi-python "bash" 2 days ago Up 2 days web root@black-pearl: /home/pirate # docker commit 04762770df2d hypriot/rpi-python root@black-pearl: /home/pirate # docker rm web |
运行新镜像
1 2 3 | #docker run -idt -P --name web hypriot/rpi-python #映射程序目录和配置文件进去 docker run -idt -P --name web - v /home/pi : /home/pi - v /home/pi/ .icedtea: /root/ .icedtea hypriot /rpi-python |
程序正常运行后,可以将这个镜像打包:
1 | docker save -o hypriot. tar hypriot /rpi-python :latest |
分发给其他树莓派运行:
1 2 3 | docker load --input hypriot. tar docker images docker run -idt -P --name web - v /home/pi : /home/pi - v /home/pi/ .icedtea: /root/ .icedtea hypriot /rpi-python |
这样子便可以利用docker工具来管理这个应用程序,比起原本复杂的环境配置要简单很多。
在查找Pi可用镜像的时候,顺便发现了一个IOT(internet of things)管理平台:resin。
参考链接:
add support to install Docker on raspbian/jessie
Getting started with Docker on your Raspberry Pi
How to get Docker running on your Raspberry Pi using Linux
Getting selenium python to work on Raspberry Pi Model B