pracpac
Practical R Packaging with Docker
VP Nagraj
Charlottesville R Users (CRU) Meetup
2025-09-24
Motivation
The pattern …
… build a Docker image to execute a pipeline as a container
- R code (in most cases distributed as a package)
- Domain-specific tools
- Some kind of execution script(s)
Motivation
https://github.com/signaturescience/k2v
FROM alpine:3.15
ARG BCFTOOLS_VERSION="1.9"
ADD src /src
WORKDIR /src
RUN apk update && apk add --no-cache gcc g++ make libc-dev ncurses-dev zlib-dev xz-dev bzip2-dev R
RUN tar -xjf bcftools-${BCFTOOLS_VERSION}.tar.bz2 && \
cd bcftools-${BCFTOOLS_VERSION} && \
make -j4 && \
make install && \
cd /src && \
rm -rf bcftools-${BCFTOOLS_VERSION} bcftools-${BCFTOOLS_VERSION}.tar.bz2
RUN tar -xjf htslib-${BCFTOOLS_VERSION}.tar.bz2 && \
cd htslib-${BCFTOOLS_VERSION} && \
make -j4 && \
make install && \
cd /src && \
rm -rf htslib-${BCFTOOLS_VERSION} htslib-${BCFTOOLS_VERSION}.tar.bz2
ADD assets /assets
ADD testdata /testdata
ADD scripts /scripts
WORKDIR /data
ENTRYPOINT ["/scripts/k2v.sh"]
Motivation
## base image
FROM rocker/r-ver:latest
## install packages
RUN Rscript -e 'install.packages("dplyr")'
Motivation
## base image
FROM rocker/r-ver:latest
## copy the renv.lock (contains dplyr and dependencies)
COPY renv.lock /renv.lock
## install renv
RUN Rscript -e 'install.packages("renv")'
## restore packages from renv.lock
RUN Rscript -e 'renv::restore(lockfile="/renv.lock")'
pracpac
pracpac
pracpac
use_docker()
create_docker_dir()
build_pkg()
renv_deps()
add_dockerfile()
add_assets()
build_image()
pracpac
pracpac
Advanced usage
- Configure base image as needed
use_docker(..., base_image = "alpine:latest")
- Customize CRAN repo used to install packages via
renv
use_docker(..., repos = "https://packagemanager.rstudio.com/cran/__linux__/jammy/latest")
- Use a different directory structure for Docker assets
use_docker(..., img_path = "../")
The process
The process
The process
- $ via internal R&D by Signature Science, LLC
- 2 day (ish) hackathon
- Output
Next
Limitations
- Not intended to necessarily write a complete Dockerfile
- Will not solve all Docker build issues
- Does not template all system libraries that may be needed
Next
Use-cases to be documented in more detail
- Shiny Server
- RStudio Server
- MLOps
- {OTHERS?}