Один файл пакетов R для нескольких файлов Dockerfile

#r #docker #package #dockerfile #install.packages

#r #docker #пакет #dockerfile #install.packages

Вопрос:

Я создал два образа Docker, один из которых — мой образ rstudio, а другой — образ cron для запуска моих cronjobs (R-скриптов).
Я создаю другие изображения (блестящие и т. Д.), Которым понадобятся точно такие же пакеты R, Чем образ cron и образ rstudio.
Поэтому я хотел бы иметь один единственный файл, в котором я мог бы перечислить все пакеты R, которые понадобятся для моих разных изображений. Структура моих папок следующая:

 ├── cron
│   ├── crontab
│   └── Dockerfile
├── rstudio
│   └── Dockerfile
├── r_packages.txt
  

В качестве примера, для файла Dockerfile моего образа rstudio я попробовал следующее:

 FROM rocker/tidyverse:3.6.1

## Create directories
RUN mkdir -p /rstudio
RUN mkdir -p /rscripts

RUN cat /home/ec2-user/r_packages.txt
  

с содержимым r_packages.txt как следует:

 R -e "install.packages(c('writexl','readxl','rjson','httr','rvest','DBI','RPostgres','stringr','xlsx','knitr','kableExtra','devtools','RSelenium'))"
  

Но я получаю следующую ошибку:

cat: /home/ec2-user/r_packages.txt : Нет такого файла или каталога

Поскольку я предполагаю r_packages.txt , что он должен находиться в том же каталоге, что и мой файл Dockerfile rstudio, но я хочу, чтобы мои r_packages были доступны для ВСЕХ моих изображений, как я могу этого добиться?

Комментарии:

1. Вы также можете запустить cron с хоста и вызвать R внутри контейнера rstudio. Используйте что-то вроде docker container exec -u rstudio -it mycontainer Rscript /path/to/script.R . Таким образом, вам нужен только один набор пакетов.

Ответ №1:

Вам нужно запустить команду сборки из каталога вашего проекта, а не там, где находятся ваши файлы Dockerfile. Причина этого в том, что Docker использует концепцию контекста, которая похожа на рабочий каталог. Docker builder не может получить доступ к файлам за пределами (выше) контекстного каталога, но он может просматривать подкаталоги. При изменении контекста из каталога с файлом Dockerfile необходимо указать используемый файл Dockerfile. Например, чтобы создать образ cron, вы должны запустить:

docker build -t cron_image_tag -f cron/Dockerfile /directory/with/r_packages.txt

Чтобы исправить cat: /home/ec2-user/r_packages.txt: No such file or directory ошибку, вам нужно сделать еще одну вещь. При использовании вы RUN запускаете эту команду внутри контейнера сборки. В контейнере не будет r_packages.txt файла, если вы явно не добавите его. Измените свой файл Dockerfile на this, чтобы исправить это:

 FROM rocker/tidyverse:3.6.1

COPY r_packages.txt /r_packages.txt
RUN cat /r_packages.txt
  

Ответ №2:

Из документации Dockerfile

 The COPY instruction copies new files or directories from <src> and adds them to the filesystem of the container at the path <dest>.

Multiple <src> resources may be specified but the paths of files and directories will be interpreted as relative to the source of the context of the build.
  

По умолчанию контекст — это место, где находится файл Dockerfile. Поэтому, когда вы создаете любой свой Dockerfile из того места, где он находится, указанный вами файл выходит за рамки (он находится в папке ниже контекста).

Чтобы решить эту проблему, создайте свой файл dockerfile из папки, содержащей ваш r_packages.txt , и сообщите команде сборки docker, где находится ваш файл Dockerfile, используя параметр командной строки -f .

docker build -f cron/Dockerfile

ПРИМЕЧАНИЕ: вам нужно будет изменить путь COPY к файлам, добавив папку, содержащую ваш файл Dockerfile (здесь cron для вашего образа cron), поскольку контекст изменился ( COPY cron/crontab /somewehere я думаю, для вашего образа cron)