Я создаю контейнер docker для приема входных данных от клиента, а затем отправляю сценарий R, который выполняет анализ данных и выводит три графика в виде PDF-файлов в рабочий каталог. Я столкнулся с проблемой необходимости двух операторов CMD в файле Dockerfile, что не разрешено движком Docker. Мне нужно, чтобы чтение данных пользователя происходило во время выполнения, чтобы набор данных мог быть изменен в зависимости от пользователя. Затем необходимо получить исходный код сценария R после того, как данные пользователя были считаны в виде объекта таблицы в рабочем пространстве R. Что происходит, данные читаются нормально, но сообщение об ошибке указывает на то, что вторая строка CMD для источника сценария R не может найти данные, которые только что были прочитаны. Я понимаю, что это потому, что каждая строка файла Docker выполняется отдельно при сборке, но я не знаю, как это исправить. Я исследовал объемы, использование супервизора и возможность использования нескольких контейнеров. Я также мог бы создать сценарий Python для динамического программирования моего сценария R, но для этого могут потребоваться две строки CMD. Мне еще предстоит найти конкретный пример c, достаточный для моей ситуации. Как бы кто-нибудь из вас решил это?
Вот мой сценарий R для создания 3 графиков из фрейма данных 'x':
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()
Вот мой Dockerfile:
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')"
В папке с путем / home / iq у меня есть сценарий под названием 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>
Изменить: I недавно обнаружил, что проблема больше связана с 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')"