R用户如何使用Docker?

R用户如何使用Docker?_第1张图片


什么是Docker

640?wx_fmt=png


Docker是“一种实现在操作系统层面的虚拟化软件,也称为容器”。这是Wikipedia的定义,对于不熟悉的人来说太晦涩难懂了。
简单说,Docker是一类程序,使得在自己的机器上(称为host)调度(启动或者停止)多个操作系统(称为容器)。假设有10台运行不同Linux系统的树莓派,每台都运行不同服务,实际上可以在自己的机器上启停这些树莓派设备。
为什么要在R中使用Docker

640?wx_fmt=png


Docker可以实现在镜像或者容器中内置环境,意味着可以在Macbook上运行Linux,或者在本机运行R 3.5而同时在虚机里运行R 3.3环境。同时,也意味着为某些特殊目的在虚拟环境中使用较老版本的环境包,而本机则保持最新状态。
这样可以解决“依赖性”问题,如果担心环境改变会影响最新环境,可以建立一个虚拟容器运行需要的环境,可以是Linux、R或者任何其他需要的包。
Docker镜像和Docker容器

640?wx_fmt=png


在机器上,需要两类东西,镜像和容器。镜像可以看做操作系统,而容器可以认为是镜像的运行态。镜像只需要运行一次,而容器则在需要时候随时启动,当然一个镜像可以同时运行多个实例。
和R对比,安装和装载package类似于镜像和容器,一个package只需要下载一次,但是可以运行多个实例。同样在metaphore概念上也有类比:通过install.packages()来编译镜像,用library()来运行镜像。
Dockerfile

640?wx_fmt=png


Docker镜像根据Dockerfile建立。Dockerfile是配置文件,其中定义了:依赖的Docker镜像,如何配置操作系统,运行容器时做什么。有点类似于R包中的DESCRIPTION NAMESPACE文件,其中也定义了依赖包,元信息,以及使用library调用后用户可用的函数和数据。
因此,可以为R写一个非常基础的Dockerfile文件,目的是可重复性。也就是说:假如生成了一个分析环境(例如,在一个R文件中定义),而且希望不管以后系统如何升级这个分析环境仍然可以工作。
首先,创建一个分析目录和Dockerfile:
 
   
  1. mkdir ~/mydocker

  2. cd ~/mydocker

  3. touch Dockerfile


假如运行程序为位于~/mydocker目录下的myscript.R:
 
   
  1. library(tidystringdist)

  2. df <- tidy_comb_all(iris, Species)

  3. p <- tidy_stringdist(df)

  4. 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版本:
 
   
  1. R.Version()$version.string


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


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

  2. RUN mkdir /home/analysis


Install our package
这条命令让R执行一些命令行,R -e "my code",用这个模式在特定日期安装依赖脚本,可以设置“repos”到特定日期,并且使用CRAN的镜像。
 
   
  1. FROM rocker/r-ver:3.4.4

  2. RUN mkdir /home/analysis

  3. RUN R -e "options(repos = \

  4. list(CRAN = 'http://mran.revolutionanalytics.com/snapshot/2019-01-06/')); \

  5. install.packages('tidystringdist')"


Aside : making it more programmable with ARG
如果使用ARG参数可以修改生成时间,参数是:--build-arg WHEN=
 
   
  1. FROM rocker/r-ver:3.4.4

  2. ARG WHEN

  3. RUN mkdir /home/analysis

  4. RUN R -e "options(repos = \

  5. list(CRAN = 'http://mran.revolutionanalytics.com/snapshot/${WHEN}')); \

  6. install.packages('tidystringdist')"


{tidystringdist} 将会安装我们要求日期的版本,即使我们在很久之后才执行这条命令。
COPY
现在,需要将主机上的分析脚本放到容器中,可以使用COPY localfile pathinthecontainer方式。注意这里的myscript.R和Dockerfile要在同一个目录下:
 
   
  1. FROM rocker/r-ver:3.4.4

  2. ARG WHEN

  3. RUN mkdir /home/analysis

  4. RUN R -e "options(repos = \

  5. list(CRAN = 'http://mran.revolutionanalytics.com/snapshot/${WHEN}')); \

  6. install.packages('tidystringdist')"

  7. COPY myscript.R /home/analysis/myscript.R


CMD
CMD是每次运行Docker都要运行的命令。
 
   
  1. FROM rocker/r-ver:3.4.4

  2. ARG WHEN

  3. RUN mkdir /home/analysis

  4. RUN R -e "options(repos = \

  5. list(CRAN = 'http://mran.revolutionanalytics.com/snapshot/${WHEN}')); \

  6. install.packages('tidystringdist')"

  7. COPY myscript.R /home/analysis/myscript.R

  8. CMD R -e "source('/home/analysis/myscript.R')"


Build 和 run

640?wx_fmt=png


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


-t name是镜像的名字,. 意味着Dockerfile在同一个目录下。
run
执行命令:
 
   
  1. docker run analysis


分析作业即可被执行。
导出容器内容

640?wx_fmt=png


现在我们迎来了下一项任务:访问由容器之外分析源(这里为p.csv)提供的相关内容;换言之,这些内容处于主机之上。相信大家都很明确,目前一切在容器之内发生的操作都只会影响到容器内部。 因此,我们需要的就是让Docker容器与主机之间共用一个文件夹。为了达成这项目标,我们将要使用所谓Volume,简单来讲,大家可以将其理解成一种告知Docker容器如何将主机上的文件夹作为容器内文件夹的方法。
这样一来,当容器被关闭之后,容器在该文件夹当中创建的所有内容都将得以保留。为此,我们将在运行容器时使用-v标志,同时配合path/from/host:/path/in/container。此外,我们还需要创建一个文件夹以接收来自容器与主机的结果:
 
   
  1. FROM rocker/r-ver:3.4.4


  2. ARG WHEN


  3. RUN mkdir /home/analysis


  4. RUN R -e "options(repos = \

  5. list(CRAN = 'http://mran.revolutionanalytics.com/snapshot/${WHEN}')); \

  6. install.packages('tidystringdist')"


  7. COPY myscript.R /home/analysis/myscript.R


  8. CMD cd /home/analysis \

  9. && R -e "source('myscript.R')" \

  10. && mv /home/analysis/p.csv /home/results/p.csv


  11. mkdir ~/mydocker/results

  12. docker run -v ~/mydocker/results:/home/results analysis


等待计算完成,然后……
 
   
  1. ls ~/mydocker/results

  2. p.csv


OK
下面我们该做什么?

640?wx_fmt=png


到这里,每一次启动这个Docker镜像时,分析都将得到执行并给出结果。另外,其中不存在依赖性问题:软件包将始终根据你的需要开始安装。虽然过程可能有点耗时,这是因为每次运行容器时软件包都会从头安装;但正如我在开头的声明中所提到,这是为了对Docker、R以及再现性做出基本介绍,旨在帮助更多初学者顺利上手Docker方案:)
下面我们再进行一点拓展讨论:
如果大家希望自己的分析以软件包版本为基础,而非以安装时间为基础,则可使用remotes::install_version()。
 
   
  1. FROM rocker/r-ver:3.4.4


  2. RUN R -e "install.packages('remotes'); \

  3. remotes::install_version('tidystringdist', '0.1.2')"


  4. ...


另外,你可以使用Volume以追踪传入容器内的数据,这样任何处于同一环境中的数据都将接受分析处理。
原文链接:https://colinfay.me/docker-r-reproducibility/


Kubernetes入门与进阶实战培训

640?wx_fmt=png


Kubernetes入门与进阶实战培训将于2019年4月19日在北京开课,3天时间带你系统学习Kubernetes,学习效果不好可以继续学习。本次培训包括:Docker基础、容器技术、Docker镜像、数据共享与持久化、Docker三驾马车、Docker实践、Kubernetes基础、Pod基础与进阶、常用对象操作、服务发现、Helm、Kubernetes核心组件原理分析、Kubernetes服务质量保证、调度详解与应用场景、网络、基于Kubernetes的CI/CD、基于Kubernetes的配置管理等,点击下面图片查看具体详情。
R用户如何使用Docker?_第2张图片

你可能感兴趣的:(R用户如何使用Docker?)