R用户如何使用Docker


什么是Docker

Docker是“一种实现在操作系统层面的虚拟化软件,也称为容器”。这是Wikipedia的定义,对于不熟悉的人来说太晦涩难懂了。

简单说,Docker是一类程序,使得在自己的机器上(称为host)调度(启动或者停止)多个操作系统(称为容器)。假设有10台运行不同Linux系统的树莓派,每台都运行不同服务,实际上可以在自己的机器上启停这些树莓派设备。

为什么要在R中使用Docker

Docker可以实现在镜像或者容器中内置环境,意味着可以在Macbook上运行Linux,或者在本机运行R 3.5而同时在虚机里运行R 3.3环境。同时,也意味着为某些特殊目的在虚拟环境中使用较老版本的环境包,而本机则保持最新状态。

这样可以解决“依赖性”问题,如果担心环境改变会影响最新环境,可以建立一个虚拟容器运行需要的环境,可以是Linux、R或者任何其他需要的包。

Docker镜像和Docker容器

在机器上,需要两类东西,镜像和容器。镜像可以看做操作系统,而容器可以认为是镜像的运行态。镜像只需要运行一次,而容器则在需要时候随时启动,当然一个镜像可以同时运行多个实例。

和R对比,安装和装载package类似于镜像和容器,一个package只需要下载一次,但是可以运行多个实例。同样在metaphore概念上也有类比:通过install.packages()来编译镜像,用library()来运行镜像。

Dockerfile

Docker镜像根据Dockerfile建立。Dockerfile是配置文件,其中定义了:依赖的Docker镜像,如何配置操作系统,运行容器时做什么。有点类似于R包中的DESCRIPTION NAMESPACE文件,其中也定义了依赖包,元信息,以及使用library调用后用户可用的函数和数据。

因此,可以为R写一个非常基础的Dockerfile文件,目的是可重复性。也就是说:假如生成了一个分析环境(例如,在一个R文件中定义),而且希望不管以后系统如何升级这个分析环境仍然可以工作。

首先,创建一个分析目录和Dockerfile:
mkdir ~/mydocker
cd ~/mydocker
touch Dockerfile

假如运行程序为位于~/mydocker目录下的myscript.R:
library(tidystringdist)
df <- tidy_comb_all(iris, Species)
p <- tidy_stringdist(df)
write.csv(p, "p.csv")

FROM

每个Dockerfile都以FROM开头,定义从哪个image开始创建。网上有很多官方发布的镜像,也可以从本地自己建一个开始。FROM定义了镜像的依赖关系,就跟R中生成一个包需要依赖一个另外的包一样(当然一般都是依赖base包)。

如果需要一个基于R的基础包,Dirk Eddelebuettel和Carl Boettiger维护了rocker,这里集中了R可以使用的所有容器镜像。基础包位于rocker/r-base下,我们期望镜像可以重现,也就是任何时候运行都会产生同样的结果,为了达到目的,在rocker/r-ver目录下维护了3.1.0版本之前的R,这样可以运行任何日期之前的程序(感谢Dirk Eddelebuettel)。接下来我们需要查找满足R要求的镜像,可以使用如下命令获得R版本:
R.Version()$version.string

因此,可以以如下标识开始一个Dockerfile:
FROM rocker/r-ver:3.4.4

RUN

到这一步,可以加入一些运行时的短指令,例如创建接收分析数据的目录:
FROM rocker/r-ver:3.4.4
RUN mkdir /home/analysis

Install our package

这条命令让R执行一些命令行,R -e "my code",用这个模式在特定日期安装依赖脚本,可以设置“repos”到特定日期,并且使用CRAN的镜像。
FROM rocker/r-ver:3.4.4
RUN mkdir /home/analysis
RUN R -e "options(repos = \
list(CRAN = 'http://mran.revolutionanalytics.com/snapshot/2019-01-06/')); \
install.packages('tidystringdist')"

Aside : making it more programmable with ARG

如果使用ARG参数可以修改生成时间,参数是:--build-arg WHEN=
FROM rocker/r-ver:3.4.4
ARG WHEN
RUN mkdir /home/analysis
RUN R -e "options(repos = \
list(CRAN = 'http://mran.revolutionanalytics.com/snapshot/${WHEN}')); \
install.packages('tidystringdist')"

{tidystringdist} 将会安装我们要求日期的版本,即使我们在很久之后才执行这条命令。

COPY

现在,需要将主机上的分析脚本放到容器中,可以使用COPY localfile pathinthecontainer方式。注意这里的myscript.R和Dockerfile要在同一个目录下:
FROM rocker/r-ver:3.4.4
ARG WHEN
RUN mkdir /home/analysis
RUN R -e "options(repos = \
list(CRAN = 'http://mran.revolutionanalytics.com/snapshot/${WHEN}')); \
install.packages('tidystringdist')"
COPY myscript.R /home/analysis/myscript.R

CMD

CMD是每次运行Docker都要运行的命令。
FROM rocker/r-ver:3.4.4
ARG WHEN
RUN mkdir /home/analysis
RUN R -e "options(repos = \
list(CRAN = 'http://mran.revolutionanalytics.com/snapshot/${WHEN}')); \
install.packages('tidystringdist')"
COPY myscript.R /home/analysis/myscript.R
CMD R -e "source('/home/analysis/myscript.R')"

Build 和 run

Build

我们的需求是:运行过去日期的分析工作,需要使用 --build-arg WHEN= 参数,只要在=后加入日期即可。在终端Dockerfile目录下,运行:
docker build --build-arg WHEN=2019-01-06 -t analysis .

-t name是镜像的名字,. 意味着Dockerfile在同一个目录下。

run

执行命令:
docker run analysis 

分析作业即可被执行。

原文链接:An Introduction to Docker for R Users(翻译:杨峰)

0 个评论

要回复文章请先登录注册