「r<-教程」R Docker 教程

原英文网址:http://ropenscilabs.github.io/r-docker-tutorial

这是专门为具有 R 和 RStudio 知识的朋友设计的 Docker 教程。该介绍旨在帮助需要 Docker 进行项目的人们。我们首先解释 Docker 是什么以及为什么有用。然后,我们将详细介绍如何将其用于可复制的分析项目。

准备

在开始之前,请根据自己的操作系统安装下面的链接的介绍安装 Docker

第一课:什么是 Docker?为什么我应该使用它?

学习目标

  • 理解 Docker 的基本思想
  • 明白为什么 Docker 非常有用

为什么我想要使用 Docker?

想象一下,你正在 R 中进行分析,然后将代码发送给朋友。 你的朋友在完全相同的数据集上运行此代码,但结果略有不同。 这可能有多种原因,例如操作系统不同,R 软件包的版本不同等。 Docker 可以解决这样的问题。

可以将Docker容器视为你计算机内部的一台计算机。 这个虚拟计算机的妙处在于你可以将其发送给你的朋友。 当他们启动计算机并运行你的代码时,他们将获得与你完全相同的结果。

简单来说,你因为下面的一些原因使用 Docker:

  • 封装所有依赖
  • 分析可重复

还有一些 Docker 可以发挥用处的地方:

  • 可移植性:由于 Docker 容器可以轻松地发送到另一台机器,因此你可以在自己的计算机上设置好所有内容,然后在更强大的机器上运行分析。
  • 可共享性:你可以将 Docker 容器发送给任何知道如何使用 Docker 的人。

基本词汇

下面会经常出现镜像和容器这两个词。映像的实例称为容器。映像是虚拟计算机的设置。如果运行此映像,将拥有它的一个实例,我们将其称为容器。可以有多个运行相同映像的容器。

第二课:在 Docker 中启动 RStudio

学习目标

  • 在 Docker 中启动 RStudio
  • 将磁盘与 Docker 镜像链接
  • 载入容器

安装

首先参考 install Docker 进行安装,没有必要完成链接中所有的教程,有需要再回看它们。

在 Docker 中启动 RStudio

要启动 Docker,我们需要做的第一件事是打开一个 Unix Shell。如果你在 Mac 或 Windows 上,在最后一步,你安装了一个叫做Docker快速启动终端;现在打开它——它看起来应该像一个普通的 shell 提示符(~$),但实际上它指向的是一个 Docker 默认运行的 linux 虚拟机,而在本教程的其余部分,除非另有说明,你应该在这里完成所有操作。如果您在 linux 机器上,那么您可以使用普通的旧终端提示符。

在 Mac上,你也可以选择终端并配置 Docker。特别是如果你得到错误不能连接到Docker守护进程。Docker 守护进程在此主机上运行吗?。在教程的某个时候,运行下面的命令可能会解决你的问题:

eval "$(docker-machine env default)"

接下来,我们将要求Docker运行一个已经存在的映像,我们将使用来自 Rockerverse Docker映像,它将允许我们在容器内运行RStudio,并且已经安装了许多有用的R包。

docker run --rm -p 8787:8787 -e PASSWORD=yourpassword rocker/verse

--rm-p-e是允许你自定义如何运行容器的标志。-p告诉 Docker 你将使用一个端口在你的浏览器中看到 RStudio(在一个位置,我们随后指定为端口 8787:8787)。—rm 确保当我们退出容器时,容器被删除。如果我们不这样做,每次我们运行一个容器,它的一个版本将被保存到我们的本地计算机。这最终会导致大量磁盘空间的浪费,直到我们手动删除这些容器。稍后,我们将向你展示如何保存容器(如果你想这样做的话)。最后,-ePASSWORD 环境变量设置为 yourpassword。在堆栈中运行带有RStudio的容器时,Rocker 需要你设置密码。出于安全考虑,我们建议你将 yourpassword 更改为您自己独特的字符串。

如果你尝试运行一个没有在本地安装的 Docker 容器,那么Docker会自动在Docker Hub(一个在线的Docker 镜像存储库)上搜索该容器,如果它存在,就下载它。

上面的命令将导致 RStudio-Server 不可见地启动。要连接到它,打开一个浏览器,输入http://,然后加上你的 ip 地址,再加上:8787。如果您运行的是 Mac 或 Windows 机器,您将在启动 Docker Quickstart终端时出现在终端中的第一行文本中找到 ip 地址。例如,你应该会看到:

                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/


docker is configured to use the default machine with IP 192.168.99.100
For help getting started, check out the docs at https://docs.docker.com

你应该在浏览器中键入 URL http://192.168.99.100:8787

如果你在一台 Linux 机器上运行,你可以使用 localhost 作为 ip 地址,例如:http://localhost:8787

这将会将你导向 RStudio 登录界面,使用下面的信息登录:

username: rstudio password: password(上面你设置过这个东西)

现在你就可以在浏览器中使用 RStudio 工作了,就像你使用 Rstudio 桌面版一样。

下面是一个截图示例:

现在试试运行下面的代码吧:

# make x the numbers from 1 to 5, and y the numbers from 6-10
x <- 1:5
y <- 6:10

# plot x against y
plot(x, y)

因为我们刚才启动镜像时使用了 --rm 标记,所以在这个机器上创建的任何东西在关闭后都会消失。你可以试试将上面的代码保存为一个文件,然后关闭浏览器,在终端上用 Control+C 关掉容器,然后重新启动容器,看是否创建的文件是否依然存在。

将磁盘与 Docker 镜像连接以便于访问和保存数据文件

既然数据文件会消失,那么我们退出容器后该如何保存我们的工作呢?一个解决的办法是将一个磁盘(例如你的本地硬盘)与一个容器连接起来,这样你就可以在本地磁盘上访问和保存数据了。

这一次当我们启动容器时使用 -v 标记指定我们项目的根目录,如下所示(你的目录可能有所不同),:左边是你本地计算机的路径,右边是容器里的路径,一般以 /home/rstudio/ 开始(这个镜像已经默认创建了用户名 RStudio 和进行了相关配置)。

docker run --rm -p 8787:8787 -v /Users/tiffanytimbers/Documents/DC/r-docker-tutorial:/home/rstudio/r-docker-tutorial rocker/verse

再一次地,在你的浏览器进行 RStudio。

这一次你在 Docker 容器中启动 RStudio 后,你可以查看到下面映射的文件目录。然后就可以载入数据进行分析工作了:

# load gapminder data from a csv on your computer
gap5yr <- read.csv(file = 'data/gapminder-FiveYearData.csv')

画一个分析图:

# load ggplot library
library(ggplot2)

# plot GDP against  life expectancy
qplot(gap5yr$lifeExp, gap5yr$gdpPercap)

# save the plot
ggsave(filename = 'data/GDP_LifeExp.pdf')

让我们将脚本保存为 plot_GDP_LifeExp.R,然后关闭容器,看在本地目录下是否能看到脚本和绘图文件。

小结

这一课我们学习了如何通过容器在浏览器中运行 RStudio。学习了 --rm 标志的作用和如何连接磁盘文件。

第三课:安装 R 包

在 RStudio 内安装 R 包

这跟我们使用 RStudio 桌面版没什么区别,试试运行:

# install package
install.packages('gapminder')

# load library
library(gapminder)

# peek at data
head(gapminder)

太好了!现在我们已经安装好包并可以进行工作。但是等等,如果我们退出了容器会发生什么?安装的包会被删除,因为我们没有保存这个版本的 Docker 镜像。我们需要创建一个镜像,这样当利用它创建一个新的容器时,gapminder 包也已经安装好了,可以直接使用。

为了做到这一点,我们需要运行 docker commit(类似 git commit)保存修改。记住,这个操作需要在关闭容器前运行,一般我们另外打开一个终端进行这个操作。

我们可以使用下面的命令进行查看(类似 linux ps 命令):

docker ps

输出应该类似下面展示,哈希值记录了容器 ID:

4a6a528b35da        rocker/verse        "/init"             2 minutes ago       Up 2 minutes        0.0.0.0:8787->8787/tcp   silly_meninsky

现在我们在新的终端中运行下面命令,并记录修改信息:

docker commit -m "verse + gapminder" 4a6a528b35da verse_gapminder

-m 指定修改信息,哈希值指定了我们要保存的容器,verse_gapminder 为保存的镜像设定了一个名字。

现在我们的电脑上就有 2 个镜像了:

docker images 
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
verse_gapminder                      latest              bb38976d03cf        57 seconds ago      1.955 GB
rocker/verse                         latest              0168d115f220        3 days ago          1.954 GB

现在你可以测试下新镜像的工作情况。

安装 R 系统外部依赖

许多 R 包有外部依赖,如 GSL, GDAL, JAGS,为了安装它们,你需要进行如下的操作:

docker ps # find the ID of the running container you want to add a package to
docker exec -it <container-id> bash # a docker command to start a bash shell in your container
apt-get install libgsl0-dev # install the package, in this case GSL

如果安装报错,先试试 apt-get update

为了保存安装的依赖,依旧需要进行修改的提交:

docker commit -m "verse + gapminder + GSL" <container id>  verse_gapminder_gsl

第四课:对 Docker Hub 推送或拉取镜像

学习目标

  • 理解镜像来自哪里
  • 从 Docker Hub 拉取镜像
  • 推送镜像到 Docker Hub

从 Docker Hub 获取镜像

Docker Hub 是一个存储 Docker 镜像的地方,当我们运行下面的命令时,软件首选检查镜像是否存在于你的计算机上。如果不存在,它会自动去 Docker Hub 搜索和下载。

docker run --rm -p 8787:8787 rocker/verse

如果你想要从 Docker Hub 上拉取镜像而不运行它,可以使用命令:

docker pull rocker/verse

将镜像放到 Docker Hub

想象一下如果你自己创建了一个镜像,然后想要与其他人分享,你可以在 https://hub.docker.com/ 创建一个账号。验证完邮箱之后,你就可以将你的镜像上传了:

  1. 登录 https://hub.docker.com/

  2. 点击创建仓库

  3. 设置名字后点击创建

  4. 使用命令行登录 Docker Hub

    docker login --username=yourhubusername --email=youremail@company.com
    

    如果没问题应该会看到下面的信息

    WARNING: login credentials saved in /home/username/.docker/config.json
    Login Succeeded
    
  5. 检查镜像的 ID

    docker images
    

    然后你会看到类似下面的输出:

    REPOSITORY              TAG       IMAGE ID         CREATED           SIZE
    verse_gapminder_gsl     latest    023ab91c6291     3 minutes ago     1.975 GB
    verse_gapminder         latest    bb38976d03cf     13 minutes ago    1.955 GB
    rocker/verse            latest    0168d115f220     3 days ago        1.954 GB
    
  6. 标记你的镜像(打标签)

    docker tag bb38976d03cf yourhubusername/verse_gapminder:firsttry
    

    这里镜像 ID 必须匹配,fisttry 是标签,一般选择一些容易识别的标签。

  7. 推送你的镜像:

    docker push yourhubusername/verse_gapminder
    

现在所有人都可以使用你的镜像了!

保存和加载镜像

将镜像推送到 Docker Hub 非常使用,但它有些缺点:

  1. 受带宽限制
  2. 推送意味着发布(私密需要额外付费)
  3. 当在一些计算节点上工作时,如果每一次你都拉取 Docker Hub 的镜像,速度会很慢

解决方案的在本地对你的镜像进行存档,这样你可以在需要的时候轻松载入。

为了这一目的,你可以使用 docker save 命令。让我们试试吧:

docker save verse_gapminder > verse_gapminder.tar

如果我们想要从存档中载入镜像,使用下面的命令:

docker load --input verse_gapminder.tar

第五课:Dockerfile

前面我们学习了一个可以在 Docker 中运行 RStudio 的基础镜像,学习如何使用 docker commit 修改镜像的内容。这是一个非常棒的技术,它让我们可以进行重复,但如果我们想要更简单地修改镜像中的内容,并有一份清晰的记录,该怎么办呢?这就是 Dockerfile 的用武之地了。

FROM rocker/verse:latest

这告诉 Docker 以 rocker/verse 基础镜像作为开始。FROM 命令必须是第一条指令。

接下来,让我们基于该基础镜像添加一层,让 gapminder 提取安装好可以直接使用:

RUN R -e "install.packages('gapminder', repos = 'http://cran.us.r-project.org')"

RUN 命令可以执行 Shell 命令,这个例子中,我们直接通过 Shell 调用包安装命令。保存你的 Dockerfile,返回终端,现在我们可以利用下面的命令构建一个自定义镜像:

docker build -t my-r-image .

-t my-r-image 指定镜像名字(要小写),. 指定构建镜像所需要的资源来源,这里指当前目录。查看镜像:

docker images

现在你可以运行你的镜像:

docker run --rm -p 8787:8787 my-r-image

在 RStudio 控制台中尝试运行:

library('gapminder')
gapminder

现在该包已经是直接可以使用了!

有时候我们想要添加一些静态文件到镜像中,这可以使用 ADD 命令:

ADD data/gapminder-FiveYearData.csv /home/rstudio/
高级技巧:缓存层

在构建和重构建你的 Docker 镜像时,你可能注意到了类似下面的输出:

Step 2 : RUN R -e "install.packages('gapminder', repos = 'http://cran.us.r-project.org')"
 ---> Using cache
 ---> fa9be67b52d1

注意到使用的是命令的缓存版本。当你重新构建映像时,Docker 会检查该映像的以前版本,以查看以前是否执行了相同的命令;每一个步骤都被保存为一个单独的层,Docker 非常聪明,可以重用那些层,如果它们没有改变,并且和前面一样的顺序。因此,一旦你弄清楚了你的安装过程的一部分(特别是如果它是一个缓慢的部分),把它放在你的Dockerfile的顶部,不要在这些行上面或中间放任何东西,特别是那些经常变化的东西;这可以大大加快你的构建过程。

简单的说,重构建只修改有变动的步骤,如果很多命令没有问题,尽量放到顶部。

小结

本节,我们学习了如何组合一个 Dockerfile 用于按我们自己的想法构建镜像,包括 3 个命令:

  • FROM 指定基础镜像
  • RUN 运行命令
  • ADD 添加文件

使用 docker build -t my-r-image . 构建。

小抄:

第六课:分享你的分析

既然我们已经学会了如何利用 Dockerfile,我们就能够将我们所有的分析发给合作者。我们将分享一个包含运行我们分析的所有依赖的镜像。

我们通过 Dockerfile 构建该镜像。让我们还是以之前使用过的 rocker 镜像开始。这一次我们使用指定的 R 版本,通过这里查看所有可获取的镜像列表。版本标签在可重复性分析中非常有用。

FROM rocker/verse:3.3.2

作为分析的一部分,我们将使用 gapminder 数据集,添加下面的内容:

RUN R -e "install.packages('gapminder', repos = 'http://cran.us.r-project.org')"

接下来将我们的分析写成脚本并将其添加到 Dockerfile 中。

library(ggplot2)
library(gapminder)

life_expentancy_plot <- ggplot(data = gapminder) + 
    geom_point(aes(x = lifeExp, y = gdpPercap, colour = continent)) 

将其添加到 Docker 镜像中的指定目录中:

ADD analysis.R /home/rstudio/

现在我们可以构建这个镜像然后检查是否我们已经具备分享的一些内容:

docker build -t my-analysis .

查看我们的分析镜像:

docker images

启动镜像:

docker run -dp 8787:8787 my-analysis

太好了,我们的分析脚本在里面,而且数据包也已经安装好了。

现在将分析推送到 dockerhub。

创建仓库后,使用下面的命令进行登录。

docker login --username=yourhubusername --email=youremail@company.com

检查镜像 ID:

docker images
REPOSITORY                         TAG                 IMAGE ID            CREATED             SIZE
my-analysis                      latest              dc63d4790eaa        2 minutes ago       3.164 GB

给要提交的镜像打标签:

docker tag dc63d4790eaa yourhubusername/gapminder_my_analysis:firsttry

推送到你创建好的仓库:

docker push yourhubusername/gapminder_my_analysis

现在你的镜像任何人都可以使用了。

合作者通过下面的命令可以下载它:

docker pull yourhubusername/gapminder_my_analysis:firsttry

更多资料:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342