kopia lustrzana https://github.com/jupyterhub/repo2docker
Add basic R + IRKernel + RStudio support
This sets up R + RStudio + IRKernel for a repository that contains: 1. A `runtime.txt` file with the text: r-<year>-<month>-<date> Where 'year', 'month' and 'date' refer to a specific date snapshot of https://mran.microsoft.com/timemachine from which libraries are to be installed. 2. An optional `install.R` file that will be executed at build time, and can be used for installing packages from both MRAN and GitHub. It currently sets up R from the ubuntu repository being used. This is unideal, and we should investigate other solutions! Fixes #24pull/210/head
rodzic
26dac5cc9b
commit
e2099dbc97
|
@ -29,6 +29,7 @@ env:
|
|||
- REPO_TYPE=conda
|
||||
- REPO_TYPE=venv
|
||||
- REPO_TYPE=julia
|
||||
- REPO_TYPE=r
|
||||
- REPO_TYPE=dockerfile
|
||||
- REPO_TYPE=external/*
|
||||
- REPO_TYPE=*.py
|
||||
|
|
|
@ -29,7 +29,8 @@ import subprocess
|
|||
|
||||
from .buildpacks import (
|
||||
PythonBuildPack, DockerBuildPack, LegacyBinderDockerBuildPack,
|
||||
CondaBuildPack, JuliaBuildPack, Python2BuildPack, BaseImage
|
||||
CondaBuildPack, JuliaBuildPack, Python2BuildPack, BaseImage,
|
||||
RBuildPack
|
||||
)
|
||||
from .utils import execute_cmd, ByteSpecification, maybe_cleanup, is_valid_docker_image_name, validate_and_generate_port_mapping
|
||||
from . import __version__
|
||||
|
@ -64,6 +65,7 @@ class Repo2Docker(Application):
|
|||
JuliaBuildPack(),
|
||||
CondaBuildPack(),
|
||||
Python2BuildPack(),
|
||||
RBuildPack(),
|
||||
PythonBuildPack()
|
||||
],
|
||||
config=True,
|
||||
|
|
|
@ -4,3 +4,4 @@ from .conda import CondaBuildPack
|
|||
from .julia import JuliaBuildPack
|
||||
from .docker import DockerBuildPack
|
||||
from .legacy import LegacyBinderDockerBuildPack
|
||||
from .r import RBuildPack
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
import re
|
||||
import os
|
||||
import datetime
|
||||
|
||||
from .python import PythonBuildPack
|
||||
|
||||
class RBuildPack(PythonBuildPack):
|
||||
"""
|
||||
Setup R for use with a repository
|
||||
|
||||
This sets up R + RStudio + IRKernel for a repository that contains:
|
||||
|
||||
1. A `runtime.txt` file with the text:
|
||||
|
||||
r-<year>-<month>-<date>
|
||||
|
||||
Where 'year', 'month' and 'date' refer to a specific
|
||||
date snapshot of https://mran.microsoft.com/timemachine
|
||||
from which libraries are to be installed.
|
||||
|
||||
2. An optional `install.R` file that will be executed at build time,
|
||||
and can be used for installing packages from both MRAN and GitHub.
|
||||
|
||||
It currently sets up R from the ubuntu repository being used. This
|
||||
is unideal, and we should investigate other solutions!
|
||||
"""
|
||||
@property
|
||||
def runtime(self):
|
||||
"""
|
||||
Return contents of runtime.txt if it exists, '' otherwise
|
||||
"""
|
||||
if not hasattr(self, '_runtime'):
|
||||
runtime_path = self.binder_path('runtime.txt')
|
||||
try:
|
||||
with open(runtime_path) as f:
|
||||
self._runtime = f.read().strip()
|
||||
except FileNotFoundError:
|
||||
self._runtime = ''
|
||||
|
||||
return self._runtime
|
||||
|
||||
@property
|
||||
def checkpoint_date(self):
|
||||
"""
|
||||
Return the date of MRAN checkpoint to use for this repo
|
||||
|
||||
Returns '' if no date is specified
|
||||
"""
|
||||
if not hasattr(self, '_checkpoint_date'):
|
||||
match = re.match(r'r-(\d\d\d\d)-(\d\d)-(\d\d)', self.runtime)
|
||||
if not match:
|
||||
self._checkpoint_date = False
|
||||
|
||||
year, month, day = [int(s) for s in match.groups()]
|
||||
|
||||
self._checkpoint_date = datetime.date(year, month, day)
|
||||
|
||||
return self._checkpoint_date
|
||||
|
||||
def detect(self):
|
||||
"""
|
||||
Check if current repo should be built with the R Build pack
|
||||
|
||||
Note that we explicitly do *not* check if a requirements.txt
|
||||
is present here (by calling super().detect()).
|
||||
"""
|
||||
return bool(self.checkpoint_date)
|
||||
|
||||
def get_path(self):
|
||||
return super().get_path() + [
|
||||
'/usr/lib/rstudio-server/bin/'
|
||||
]
|
||||
|
||||
def get_env(self):
|
||||
return super().get_env() + [
|
||||
# This is the path where user libraries are installed
|
||||
('R_LIBS_USER', '${APP_BASE}/rlibs')
|
||||
]
|
||||
|
||||
def get_packages(self):
|
||||
return super().get_packages().union([
|
||||
'r-base',
|
||||
# For rstudio
|
||||
'psmisc',
|
||||
'libapparmor1',
|
||||
'sudo',
|
||||
'lsb-release'
|
||||
])
|
||||
|
||||
def get_build_scripts(self):
|
||||
mran_url = 'https://mran.microsoft.com/snapshot/{}'.format(
|
||||
self.checkpoint_date.isoformat()
|
||||
)
|
||||
rstudio_url = 'https://download2.rstudio.org/rstudio-server-1.1.419-amd64.deb'
|
||||
# This is MD5, because that is what RStudio download page provides!
|
||||
rstudio_checksum = '24cd11f0405d8372b4168fc9956e0386'
|
||||
return super().get_build_scripts() + [
|
||||
(
|
||||
"root",
|
||||
r"""
|
||||
mkdir -p ${R_LIBS_USER} && \
|
||||
chown -R ${NB_USER}:${NB_USER} ${R_LIBS_USER}
|
||||
"""
|
||||
),
|
||||
(
|
||||
"root",
|
||||
# We set the default CRAN repo to the MRAN one at given date
|
||||
# We set download method to be curl so we get HTTPS support
|
||||
r"""
|
||||
echo "options(repos = c(CRAN='{mran_url}'), download.file.method = 'libcurl')" > /etc/R/Rprofile.site
|
||||
""".format(mran_url=mran_url)
|
||||
),
|
||||
(
|
||||
"root",
|
||||
# Install RStudio!
|
||||
r"""
|
||||
curl -L --fail {rstudio_url} > /tmp/rstudio.deb && \
|
||||
echo '{rstudio_checksum} /tmp/rstudio.deb' | md5sum -c - && \
|
||||
dpkg -i /tmp/rstudio.deb && \
|
||||
rm /tmp/rstudio.deb
|
||||
""".format(
|
||||
rstudio_url=rstudio_url,
|
||||
rstudio_checksum=rstudio_checksum
|
||||
)
|
||||
),
|
||||
(
|
||||
"${NB_USER}",
|
||||
# Install a pinned version of IRKernel and set it up for use!
|
||||
r"""
|
||||
R --quiet -e "install.packages('devtools')" && \
|
||||
R --quiet -e "devtools::install_github('IRkernel/IRkernel', ref='0.8.11')" && \
|
||||
R --quiet -e "IRkernel::installspec(prefix='${NB_PYTHON_PREFIX}')"
|
||||
"""
|
||||
),
|
||||
(
|
||||
"${NB_USER}",
|
||||
# Install nbrsessionproxy
|
||||
r"""
|
||||
pip install --no-cache-dir nbrsessionproxy==0.6.1 && \
|
||||
jupyter serverextension enable nbrsessionproxy --sys-prefix && \
|
||||
jupyter nbextension install --py nbrsessionproxy --sys-prefix && \
|
||||
jupyter nbextension enable --py nbrsessionproxy --sys-prefix
|
||||
"""
|
||||
)
|
||||
|
||||
]
|
||||
|
||||
def get_assemble_scripts(self):
|
||||
assemble_scripts = super().get_assemble_scripts()
|
||||
if os.path.exists('install.R'):
|
||||
assemble_scripts += [
|
||||
(
|
||||
"${NB_USER}",
|
||||
"Rscript install.R"
|
||||
)
|
||||
]
|
||||
|
||||
return assemble_scripts
|
|
@ -0,0 +1 @@
|
|||
install.packages("ggplot2")
|
|
@ -0,0 +1 @@
|
|||
r-2017-10-24
|
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env Rscript
|
||||
library('ggplot2')
|
Ładowanie…
Reference in New Issue