如何在Dockerfile中跨多个CMD语句持久化一个R工作空间?

问题描述 投票:1回答:1

我正在创建一个 docker 容器,以接受来自客户端的输入数据,然后将一个 R 脚本作为源码,在给定的数据上运行分析,并将三张图以 PDF 格式输出到工作目录中。 我遇到的问题是,在Docker文件中需要两个CMD语句,这是不被Docker引擎允许的。 我需要在运行时读取用户的数据,这样数据集就可以根据用户的情况进行更改。然后,R脚本需要在R工作空间中以表对象的形式读取用户的数据后,再进行源码。 出现的情况是,数据读进去就好了,但是错误信息显示,第二行CMD行,要来源R脚本,找不到刚刚读进去的数据。 我理解这是因为Dockerfile的每一行在构建时都是单独执行的,但我不知道如何解决这个问题。 我研究了卷,使用supervisor,以及使用多个容器的可能性。 我也有可能做一个Python脚本来动态编程我的R脚本,但这可能还是需要两行CMD。 我还没有找到一个足够具体的例子来说明我的情况。 你们谁能解决这个问题?

这是我的R脚本,从一个数据框架 "x "中创建3个图。

library(iq)
norm_data <- iq::preprocess(x, median_normalization = FALSE, pdf_out = NULL)
protein_list <- iq::create_protein_list(norm_data)

# basic protein plot
pdf(file = "Protein P00366.pdf")
iq::plot_protein(protein_list$P00366, main = "Protein P00366", split = NULL)
dev.off()

protein_table <- iq::create_protein_table(protein_list)

#MaxLFQ plot
pdf(file = "MaxLFQ quantification of P00366.pdf")
iq::plot_protein(rbind(protein_list$P00366, 
                       MaxLFQ = iq::maxLFQ(protein_list$P00366)$estimate), 
                 main = "MaxLFQ quantification of P00366", 
                 col = c(rep("gray", nrow(protein_list$P00366)), "green"), 
                 split = NULL)  
dev.off()

# ground truth
MaxLFQ_estimate <- iq::maxLFQ(protein_list$P12799)$estimate

ground_truth <-  log2(rep(c(200, 125.99, 79.37, 50, 4, 2.52, 1.59, 1), each = 3))
ground_truth <- ground_truth - mean(ground_truth) + mean(MaxLFQ_estimate)

#ground truth plot
pdf(file = "P12799 MaxLFQ versus groundtruth.pdf")
iq::plot_protein(rbind(MaxLFQ = MaxLFQ_estimate,
                       Groundtruth = ground_truth), 
                 main = "P12799 - MaxLFQ versus groundtruth",  
                 split = 0.75, 
                 col = c("green", "gold"))  
dev.off()

这是我的Docker文件

FROM r-base:latest

ENV SCRIPT=""
ENV DATA=""                            

RUN R -e "install.packages('iq', repos='http://cran.rstudio.com/')"

WORKDIR /home/iq/

CMD R -e "x <- read.table(\"$DATA\", header = TRUE, sep = ",", fill = TRUE)" \
   && R -e "source('$SCRIPT')"

在一个路径为homeiq的文件夹里 我有一个叫iqTest.R的脚本 Dockerfile和data.csv 我一直在用下面的命令构建和运行我的容器。

$ cd iq
$ docker build -t my_image .
$ docker run -it -v /home/user/iq:/home/iq --env DATA=data.csv --env SCRIPT=iqTest.R my_image:latest

在尝试运行后,我从R工作区得到以下错误信息。

> source('iqTest.R')
Error in iq::preprocess(x, median_normalization = FALSE, pdf_out = NULL) : 
  object 'x' not found
Calls: source -> withVisible -> eval -> eval -> <Anonymous>

编辑:我最近发现,这个问题更多的是与R有关:你可以使用一个 ; 来连接多行R代码,这样就解决了多条CMD语句的问题。愿以此为例,给正在连接R和Docker.例如新的Dockerfile,用分号连接行。

FROM r-base:latest

ENV SCRIPT=""
ENV DATA="" 

RUN mkdir /home/analysis/

RUN R -e "install.packages('iq', repos='http://cran.rstudio.com/')"

WORKDIR /home/analysis/

CMD R -e "x = read.csv(\"$DATA\", header = TRUE, sep = ",", fill = TRUE); source('$SCRIPT')"

r docker dockerfile persistence interactive
1个回答
0
投票

如果你想通过一个环境变量来配置数据路径,那么我建议在你的脚本中用以下方法来访问这个变量 Sys.getenv(). 这也允许你使用 Rscript 而不是 R -e "source....

下面是我的工作原理。

script.R

cat(Sys.getenv('SCRIPT'), '\n');
cat(Sys.getenv('DATA'), '\n')

Docker文件

FROM r-base:latest

ENV SCRIPT="script.R"
ENV DATA="data.csv"

WORKDIR /workspace

CMD R -q -e "source('$SCRIPT')"
# alternative: CMD Rscript $SCRIPT

使用方法

daniel@nuest /tmp/stackoverflow []$ docker build --tag stackoverflow .
Sending build context to Docker daemon  4.608kB
Step 1/5 : FROM r-base:latest
 ---> 46edce0e80af
Step 2/5 : ENV SCRIPT="script.R"
 ---> Using cache
 ---> 8f26d34d9c0a
Step 3/5 : ENV DATA="data.csv"
 ---> Using cache
 ---> 16c83c16a4c8
Step 4/5 : WORKDIR /workspace
 ---> Running in fce8619af30b
Removing intermediate container fce8619af30b
 ---> a8278f609d9a
Step 5/5 : CMD R -q -e "source('$SCRIPT')"
 ---> Running in 765bafeb8681
Removing intermediate container 765bafeb8681
 ---> ff7d7b09dffb
Successfully built ff7d7b09dffb
Successfully tagged stackoverflow:latest
daniel@nuest /tmp/stackoverflow []$ docker run --rm -it -v $(pwd):/workspace stackoverflow
> source('script.R')
script.R 
data.csv 
> 
> 

或者,你可以尝试将数据路径作为参数传递给你的脚本文件,参见 https:/swcarpentry.github.IOR-novice-inflammation05-cmdline。

顺便说一句:钉一个特定的R版本比使用 :latest,以保证重复性。

© www.soinside.com 2019 - 2024. All rights reserved.