Skip to contents

Introduction

dockitect is an R package that simplifies Docker containerization for R projects. It provides a programmatic, pipe-friendly interface for creating, modifying, and validating Docker configurations. This vignette introduces key concepts and features to help you get started with containerizing your R projects.

For those new to Docker, here’s a quick overview of relevant terms:

  • Docker: A platform that enables you to package applications with all their dependencies into standardized units called containers
  • Docker image: A read-only template with instructions for creating a Docker container
  • Docker container: A runnable instance of an image
  • Dockerfile: A text file that contains instructions for building a Docker image
  • Dockerfile Instructions: Commands like FROM, RUN, COPY, etc., that define the image

Installation

You can install the development version of dockitect from GitHub:

# install.packages("remotes")
remotes::install_github("coatless-rpkg/dockitect")

Access the package by loading it:

Package Overview

dockitect uses a consistent naming convention to make functions easy to discover:

  • dockerfile() creates a Dockerfile object
  • dockerignore() creates a .dockerignore object
    • di_*() functions manage .dockerignore patterns (e.g., di_add())
  • dk_*() functions create Dockerfiles from templates or existing projects

Creating Basic Dockerfiles

We’ll next turn our attention to creating a Dockerfile programmatically. The process involves creating a Dockerfile object and adding various instructions to it through a series of pipe operations.

Creating a Dockerfile Object

Start by creating a new Dockerfile object:

# Create a new Dockerfile object
df <- dockerfile()
print(df)
#> Empty Dockerfile

Congratulations! You’ve created your first (empty) Dockerfile object. Now let’s add some instructions.

Adding Docker Instructions

To add instructions to the Dockerfile, use the dfi_*() functions. For example, to set the base image:

# Create a Dockerfile for an R script
df <- dockerfile() |>
  dfi_from("rocker/r-ver:4.4.0")  # Base image with R 4.4.0

You can print the Dockerfile to see the added instruction:

print(df)
#> FROM rocker/r-ver:4.4.0

Usually, you’ll add multiple instructions to the Dockerfile. Let’s add a few more instructions to the Dockerfile so that we can run a script:

# Create a Dockerfile for an R script
df <- dockerfile() |>
  dfi_from("rocker/r-ver:4.4.0") |>   # Base image with R 4.4.0
  dfi_label(maintainer = "user@example.com") |>  # Add metadata
  dfi_workdir("/app") |>              # Set working directory
  dfi_copy("analysis.R", "/app/") |>  # Copy R script to container
  dfi_cmd("Rscript /app/analysis.R")  # Command to run when container starts

# Print the Dockerfile
print(df)
#> FROM rocker/r-ver:4.4.0
#> LABEL maintainer="user@example.com"
#> WORKDIR /app
#> COPY analysis.R /app/
#> CMD ["Rscript","/app/analysis.R"]

This example shows the most common Docker instructions:

  • FROM: Specifies the base image (here using the Rocker Project’s R image)
  • LABEL: Adds metadata to the image
  • WORKDIR: Sets the working directory inside the container
  • COPY: Copies files from your local system to the container
  • CMD: Defines the default command to run when starting the container

Adding Multiple Commands

For RUN instructions with multiple commands, you can pass a character vector:

dockerfile() |>
  dfi_from("rocker/r-ver:4.4.0") |>
  dfi_run(c(
    "apt-get update",
    "apt-get install -y libcurl4-openssl-dev",
    "apt-get clean"
  ))
#> FROM rocker/r-ver:4.4.0
#> RUN apt-get update && apt-get install -y libcurl4-openssl-dev && apt-get clean

Writing to a File

To save your Dockerfile:

# Write to the default "Dockerfile" file
write_dockerfile(df)

# Or specify a different filename
write_dockerfile(df, "path/to/Dockerfile")

By default, write_dockerfile() formats multi-line instructions for readability.

[!IMPORTANT] The multi-line instructions for is still a work-in-progress!

Using Templates

Creating Dockerfiles from scratch can be repetitive. dockitect provides templates for common R project types that follow best practices.

Base R Template

This template creates a basic R environment:

# Create a basic R image
df_base <- dk_template_base(
  r_version = "4.4.0",                     # Specify R version
  additional_pkgs = c("dplyr", "ggplot2")  # Add R packages
)
#> 
#>  Updated metadata database: 5.49 MB in 10 files.
#> 
#>  Updating metadata database
#>  Updating metadata database ... done
#> 
#> ! Failed to update system requirement mappings, will use cached mappings.
print(df_base)
#> FROM rocker/r-ver:4.4.0
#> LABEL maintainer="runner" description="Base R image for analysis"
#> WORKDIR /app
#> RUN R -e "install.packages(c('dplyr', 'ggplot2'), repos='https://cloud.r-project.org/')"
#> RUN mkdir -p /app/scripts /app/data /app/output
#> VOLUME /app/data
#> VOLUME /app/output
#> CMD ["R","--no-save"]

Shiny App Template

For Shiny web applications:

# Create a Shiny app image
df_shiny <- dk_template_shiny(
  r_version = "4.4.0",                     # Specify R version
  port = 3838,                             # Port for Shiny server
  additional_pkgs = c("dplyr", "ggplot2")  # Add R packages
)
print(df_shiny)
#> FROM rocker/shiny:4.4.0
#> LABEL maintainer="runner" description="Shiny application"
#> RUN apt-get update -y && apt-get install -y --no-install-recommends make zlib1g-dev && apt-get clean && rm -rf /var/lib/apt/lists/*
#> RUN R -e "install.packages(c('shiny', 'dplyr', 'ggplot2'), repos='https://cloud.r-project.org/')"
#> COPY . /srv/shiny-server/app
#> WORKDIR /srv/shiny-server/app
#> EXPOSE 3838
#> CMD ["shiny-server"]

Plumber API Template

For RESTful APIs with Plumber:

# Create a Plumber API image
df_plumber <- dk_template_plumber(
  r_version = "4.4.0",  # Specify R version
  port = 8000,  # Port for API
  additional_pkgs = c("dplyr", "jsonlite")  # Add R packages
)
print(df_plumber)

[!NOTE]

The dk_template_plumber() function template is still a work-in-progress!

Managing .dockerignore Files

A .dockerignore file tells Docker which files to exclude from the build context, improving build performance and reducing image size.

Creating a .dockerignore File

In dockitect, you can create a dockerignore object and add patterns:

# Create a new .dockerignore object
di <- dockerignore()

# Add patterns to ignore
di <- di |>
  di_add("*.Rdata") |>     # Ignore R data files
  di_add("data/*.csv") |>  # Ignore CSV files in data directory
  dk_template_ignore_git() # Add common Git patterns

print(di)
#> *.Rdata
#> data/*.csv
#> .git/
#> .gitignore
#> .gitattributes
#> .github/
#> .gitlab-ci.yml

Using Templates for Common Patterns

dockitect includes templates for common ignore patterns:

# Create a template for R projects
di_r <- dk_template_ignore_r()
print(di_r)
#> .Rproj.user/
#> .Rhistory
#> .RData
#> .Ruserdata
#> *.Rproj
#> *.rds
#> .lintr
#> *.Rcheck/
#> .Renviron
#> .Rprofile
#> renv/library/
#> renv/staging/
#> renv/python/
#> renv/local/
#> packrat/lib*/
#> packrat/src/

# Create a template for Git files
di_git <- dk_template_ignore_git()
print(di_git)
#> .git/
#> .gitignore
#> .gitattributes
#> .github/
#> .gitlab-ci.yml

Combining Templates

You can combine templates using c():

# Combine templates
di_combined <- c(
  dk_template_ignore_git(),  # Git files
  dk_template_ignore_r()     # R files
)

# Add custom patterns
di_combined <- di_add(di_combined, "my-custom-pattern")
print(di_combined)
#> .git/
#> .gitignore
#> .gitattributes
#> .github/
#> .gitlab-ci.yml
#> .Rproj.user/
#> .Rhistory
#> .RData
#> .Ruserdata
#> *.Rproj
#> *.rds
#> .lintr
#> *.Rcheck/
#> .Renviron
#> .Rprofile
#> renv/library/
#> renv/staging/
#> renv/python/
#> renv/local/
#> packrat/lib*/
#> packrat/src/
#> my-custom-pattern

Writing to a File

To save your .dockerignore:

# Write to .dockerignore file
write_dockerignore(di_combined)

Fin

This vignette introduced the basic functionality of dockitect for creating Dockerfile files and managing .dockerignore files. These core features will help you containerize your R projects more efficiently.

Future vignettes will cover:

  • Advanced Dockerfile Manipulation: Modifying, grouping, and sorting instructions
  • Generating Dockerfiles from Projects: Creating Dockerfiles from R sessions, renv.lock files, DESCRIPTION files, and R scripts
  • Custom Templates: Creating and using your own Dockerfile templates
  • Multi-stage Builds: Creating optimized images with multi-stage builds
  • Best Practices: Guidelines for creating efficient and secure Docker images for R

As this package is in development, please refer back to the function documentation and visit the package website.