在挂载包含包的卷时在一个容器中执行R文件

  • 本文关键字:一个 文件 执行 包含包 r docker
  • 更新时间 :
  • 英文 :


我在Windows 11上使用WSL2和Ubuntu。我有以下文件夹设置:

Code
|--- Dockerfile
|--- iris.R
R
|--- Dockerfile
|--- packages.R
|--- packages.txt
Results (an empty folder)

我的目标是:

  1. 基于R文件夹创建一个容器,生成一个卷。
  2. 将卷挂载到第二个容器上。
  3. 让它检测软件包已经从卷中安装。
  4. 执行iris.R。
  5. 将其输出保存到结果文件夹,挂载到我的本地结果文件夹(我暂时不担心这一步,但如果你想告诉我如何做这一步,尽一切可能)。

我明白最终的目标应该是把这些放到一个docker-compose文件中,但是在我去那里之前,我想让它们直接在CLI中工作。

步骤1

R/Dockerfile:

#### INITIAL SETUP
FROM r-base:4.2.2
# Define the date (YYYY-MM-DD) at build time
ARG WHEN
ENV WHEN = $WHEN
# Copy packages.txt
COPY . /home/
# Define the working directory
WORKDIR /home/
# Execute R from the terminal
CMD ["Rscript", "packages.R"]

R/包。R:

when <- gsub("= ", "", Sys.getenv("WHEN"))
options(repos = list(CRAN = paste0('http:/mran.revolutionanalytics.com/snapshot/', when)))
install.packages(readLines('packages.txt'))

R/packages.txt:

ggplot2

以下是我在R文件夹中执行的命令:

docker build --network=plot-network:first --build-arg WHEN=2022-12-29 -t package:first .
docker volume create packages
docker run -d --network=plot-network:first -v packages:/home --rm package:first  

我知道这会创建一个packages卷,这是必要的,因为一旦容器完成,数据(即已安装的包)就不会保留。

步骤2 - 3

这就是我被卡住的地方。现在我们进入Code文件夹:

代码/Dockerfile:

#### INITIAL SETUP
FROM r-base:4.2.2
# Set an environment variable at runtime for the separate directory
ENV MAINDIR /home/
# Copy the file to a path in the container
COPY . ${MAINDIR}
# Set working directory
WORKDIR $MAINDIR
# Append Rscript to code
ENTRYPOINT ["Rscript"]

代码/虹膜。R:

library(ggplot2)
args <- commandArgs(trailingOnly = TRUE)
p <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width,
color = Species)) +
geom_point() +
geom_smooth(method = "lm") +
theme_bw() +
theme(panel.grid = element_blank()) +
xlab("Sepal Length") +
ylab("Sepal Width") +
scale_x_continuous(limits = c(4, 8), breaks = seq(4, 8, 0.5)) +
scale_y_continuous(limits = c(2, 5), breaks = 2:5)
ggsave(filename = args[1])
显然第一个要执行的命令是
docker build -t plot:first .

第二个命令不那么明显。Rscript iris.R应该执行iris.R,但是我还没有弄清楚如何正确地挂载卷,以便检测到iris.R

docker run --network=plot-network:first -v packages:/home/ plot:first iris.R
Fatal error: cannot open file 'iris.R': No such file or directory

我注释掉了上面的ENTRYPOINT ["Rscript"],并试图找出为什么iris.R没有显示,因为Rscript iris.R告诉我它不在目录中,并执行以下命令:

docker run --network=plot-network:first -v packages:/home/ plot:first R -e "list.files()"

这列出了目录中的文件,并给了我以下内容:

list.files()
[1] "docker"       "Dockerfile"   "packages.R"   "packages.txt"

不检测虹膜。

它似乎检测到原来在R文件夹中的文件。但值得关注的是,它没有检测到我认为我放入packages卷中的已安装的软件包。

步骤1中的docker run命令在安装包时,R告诉我:

Installing package into ‘/usr/local/lib/R/site-library’
(as ‘lib’ is unspecified)

,显然这个/usr/目录没有被带入卷(如上面的list.files()所证明的)。

我在这里做错了什么?

为什么这样做?

我被其他人问过这个问题,他们给了我一些帮助:这样做的原因是因为包安装很耗时,最好只引用一个已经安装了包的容器,这样我就不必每次构建新容器时都重新安装包。

从"为什么这样做"我理解你想在构建新容器时跳过安装包。

因此,我建议跳过卷部分,只使用第一个容器作为第二个容器的源。

Code/Dockerfile的第一行应该是:

From package:first

卷用于同时在多个容器之间共享数据,所以除非您想要,否则我不建议在这种情况下使用它。

它似乎检测到原来在R文件夹中的文件。但令人担忧的是,它没有检测到我认为我扔进包卷的已安装的包。

这是因为卷挂载到/home目录,在这里,包被下载并安装在不同的目录中。从包容器的日志中:

安装/usr/local/lib/R/site-library/00 lock-tibble/00新/宠物猫/libs

下载的源包在"/tmp/Rtmp7ow0xd/downloaded_packages">

使用卷将增加不必要的复杂性,因为安装的包将被分成多个文件夹。

最后是虹膜。没有找到R文件,因为卷挂载用包容器的文件覆盖了它。

我建议如下:

  1. 保持R/Dockerfile原样
  2. 构建包容器。
  3. 使用packages容器作为plot容器
  4. 的源
  5. 建立地块容器
  6. 运行没有卷的plot容器(/home目录)还会有文件的包容器,可以添加一个在复制虹膜之前,要把线清理干净。

相关内容

最新更新